👻

[Nuxt3] using p5.js

2024/07/10に公開

Introduction

I'll show you Two examples of using p5.js on Nuxt.js framework(Nuxt3).

[Environment]
node: v20.15.1
nuxt: 3.12.3
os: windows11

  1. use javascript directly

We can put "p5.min.js" and your script(sketch.js) in the "public" directory.
And We can import these scripts into the vue file in the pages directory.
But, I think that this is not what you want.
I write this way just as my memo.

public\p5.min.js
public\sketch.js
pages\drawing.vue
  1. use p5.js module in Nuxt3

We can import "p5.js" as a module in the vue file(Canvas.vue) in the components directory.
And we can use that component in the vue file(drawing2.vue) in the pages directory.
I believe this is what you want.

components\Canvas.vue
pages\drawing2.vue

note:
In this example's second part "use p5.js module in Nuxt3", the code for "p5.js" didn't work well with typescript.
So I wrote the code in javascript only.
But recently I solve the problem, and write this post.
[Nuxt3] using p5.js with Typescript


1. use javascript directly

Let's download "p5.min.js" from p5js's "Download page".
Download Single Files

And put the file into the "public directory".

public\p5.min.js

note: You can use the file from cdn directly. In this case, you don't need to download it.
Use p5.js from CDN

Then create sketch.js into the "public directory".

public\sketch.js
function setup() {
  createCanvas(400, 400);
}

function draw() {
  // background(220);
  background("aqua");

  //circle in the center with a width of 100
  circle(200, 200, 100);

  //when mouse button is pressed, circles turn black
  if (mouseIsPressed === true) {
    fill(0);
  } else {
    fill(255);
  }

  //white circles drawn at mouse position
  circle(mouseX, mouseY, 100);
}

Then create drawing.vue into the "pages directory".

pages\drawing.vue
<template>
    <div>
        drawing content
    </div>
</template>

<script setup lang="ts">
useHead({
  script: [
    {
      src: 'p5.min.js',
      // valid options are: 'head' | 'bodyClose' | 'bodyOpen'
      tagPosition: 'bodyClose'
    },
    {
      src: 'sketch.js',
      // valid options are: 'head' | 'bodyClose' | 'bodyOpen'
      tagPosition: 'bodyClose'
    }
  ]
})
</script>

note: You might get an error by typescript, that says it can't resolve the "useHead" function.
If so, you need to install the "vue-tsc" module using this command, below.

npm i vue-tsc -D

Now you can see the page,

http://localhost:3000/drawing

like this.

note: updated at 2024/7/17
Could you ignore the TEXT messages in this picture, because these TEXT is not related to this post and "sketch.js". These TEXT come from another script.
Just focus on the canvas area!

2. use p5.js module in Nuxt3

At first, you need to install p5 module.

npm i p5
npm i @types/p5 -D

Then, Let's create drawing2.vue into the "pages directory".

pages\drawing2.vue
<template>
    <div id="app">
        <Canvas />
    </div>
</template>

// updated at 2024/7/17
<!-- <script> -->
// import Canvas from '@/components/Canvas'
// // Note: @ refers to the /src/ folder
// 
// export default {
//     name: 'App',
//     components: {
//         Canvas
//     }
// }
<!-- </script> -->

note: updated at 2024/7/17
I noticed this thing recently.
When we use the "components", we don't need to import those components.
Because Nuxt automatically imports the components.
So I commented out the unnecessary parts in the code "drawing2.vue"


Then create Canvas.vue into the "components directory".

components\Canvas.vue
<template>
    <div id="canvas"></div>
</template>
  
<script>
export default {
    name: 'App',
    async mounted() {
        const { default: P5 } = await import('p5')

        const script = p5 => {
            // These are your typical setup() and draw() methods
            p5.setup = () => {
                p5.createCanvas(window.innerWidth, window.innerHeight);
            };
            p5.draw = () => {
                p5.clear();
                p5.background("aqua");
                p5.ellipse(p5.mouseX, p5.mouseY, 40, 40);

                //when mouse button is pressed, circles turn black
                if (p5.mouseIsPressed === true) {
                    p5.fill(0);
                } else {
                    p5.fill(255);
                }
            };
        }
        // Attach the canvas to the div
        const p5canvas = new P5(script, 'canvas');
    },
}
</script>

Now you can see the page,

http://localhost:3000/drawing2

like this.

note: updated at 2024/7/17
Could you ignore the TEXT messages in this picture, because these TEXT is not related to this post, "pages\drawing2.vue" and "components\Canvas.vue". These TEXT come from another script.
Just focus on the canvas area!

Discussion