Hi, I'm Lylia!
Full-stack web developer and web designer
Learn how to seamlessly integrate p5.js into your Nuxt project to create captivating hero sections.
Jan 28, 2025
Today, I will show you how to integrate p5.js in your next Nuxt project and demonstrate creative ways to use P5 in your projects.
First, you’ll have to install p5 using your favorite package manager:
npm install p5
We will then create a component in which we will set up p5.js and use it later in our project.
// components/nuxt-p5.vue
<template>
<div ref="canvasContainer"></div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount } from "vue";
// Define props for the component
const props = defineProps({
sketch: {
type: Function,
required: true,
},
});
const canvasContainer = ref(null); // Reference for the canvas container
defineExpose(['canvasContainer']); // Expose the canvas container for potential advanced use cases
let p5Instance = null; // Variable to hold the p5 instance
// Lifecycle hook: Mounting the component
onMounted(async () => {
const { default: P5 } = await import("p5");
p5Instance = new P5(props.sketch, canvasContainer.value); // Initialize the p5 instance with the provided sketch
});
// Lifecycle hook: Cleaning up the p5 instance before unmounting
onBeforeUnmount(() => {
if (p5Instance) {
p5Instance.remove(); // Remove the p5 instance to free resources
}
});
</script>
We are now ready to add P5.js to our components. As an example, we will build a dynamic hero section.
Let’s create a hero section that combines text and a visually appealing animated background powered by p5.js. The following code achieves this:
<template>
<section class="font-sans relative min-h-screen overflow-hidden">
<!-- Include the NuxtP5 component with the sketch prop -->
<NuxtP5 :sketch="heroSketch" />
<!-- Overlay text content -->
<div
class="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 text-center text-white z-10"
>
<h1 class="text-5xl mb-6">Welcome to Dynamic Vue</h1>
<p class="text-3xl mb-4">
Build stunning and interactive web experiences with ease.
</p>
<button
class="bg-blue-700 p-4 rounded-sm hover:bg-blue-500 transition-all transition-ease"
>
Get Started
</button>
</div>
</section>
</template>
<script setup>
// Sketch function for the hero section background
const heroSketch = (p5) => {
let particles = []; // Array to hold the particles
// Setup function: Initialize the canvas and particles
p5.setup = () => {
p5.createCanvas(window.innerWidth, window.innerHeight); // Fullscreen canvas
for (let i = 0; i < 100; i++) {
particles.push(new Particle(p5)); // Generate particles
}
};
// Handle window resizing to ensure the canvas adjusts
p5.windowResized = () => {
p5.resizeCanvas(p5.windowWidth, p5.windowHeight);
};
// Draw function: Called every frame to update and render the particles
p5.draw = () => {
p5.background(20, 20, 40); // Deep blue background
for (let particle of particles) {
particle.update(); // Update particle positions
particle.show(); // Render the particles
}
};
// Particle class
class Particle {
constructor(p5) {
this.p5 = p5;
this.pos = p5.createVector(p5.random(p5.width), p5.random(p5.height)); // Random initial position
this.vel = p5.createVector(p5.random(-1, 1), p5.random(-1, 1)); // Random velocity
this.radius = p5.random(2, 2); // Fixed particle size
}
// Update the particle's position and handle boundary collisions
update() {
this.pos.add(this.vel);
if (this.pos.x > this.p5.width || this.pos.x < 0) {
this.vel.x *= -1;
}
if (this.pos.y > this.p5.height || this.pos.y < 0) {
this.vel.y *= -1;
}
}
// Render the particle
show() {
this.p5.noStroke();
this.p5.fill(100, 200, 255, 150); // Soft blue particle color
this.p5.ellipse(this.pos.x, this.pos.y, this.radius);
}
}
};
</script>
onMounted
lifecycle hook to dynamically import the p5.js library and initialize a sketch.onBeforeUnmount
hook ensures proper cleanup of resources by removing the p5 instance.NuxtP5
component and pass the heroSketch
function as a prop.particles
are lightweight objects that bounce within the canvas, creating a visually pleasing effect.div
containing the hero content is styled using TailwindCSS.absolute
positioning ensures the text is centered on top of the animated background.By integrating p5.js into your Nuxt project, you can create stunning, interactive experiences like this dynamic hero section. The modularity of the NuxtP5
component allows you to reuse it for any other p5.js-based visuals in your app. Experiment with different sketches to bring your unique vision to life!
I'm a freelance fullstack developer, working with Vue, Svelte, TypeScript, and Headless CMSes.
I'm interested in AI, web development, and creative coding. I love helping my clients achieve their goals by focusing on accessibility and using technology to empower all people.
Feel free to reach out to me here.