This article is part of a series on my experiences with Nuxt.js that I built into the nuxt-toolkit by OverScore Media
overscore-media / nuxt-toolkit
A bunch of useful example code snippets for use with Nuxt.js
See a live example at https://nuxt-toolkit.overscore.media! :]
Ah, particle effects. Wondrous things, really. And I can think of no better particle effects library for the web (that isn't something related to game development or 3D rendering) than Particles.JS.
VincentGarreau / particles.js
A lightweight JavaScript library for creating particles
particles.js
A lightweight JavaScript library for creating particles.
Demo / Generator
Configure, export, and share your particles.js configuration on CodePen:
http://vincentgarreau.com/particles.js/
CodePen demo:
http://codepen.io/VincentGarreau/pen/pnlso
Usage
Load particles.js and configure the particles:
index.html
<div id="particles-js"></div>
<script src="particles.js"></script>
app.js
/* particlesJS.load(@dom-id, @path-json, @callback (optional)); */
particlesJS.load('particles-js', 'assets/particles.json', function() {
console.log('callback - particles.js config loaded');
});
particles.json
{
"particles": {
"number": {
"value": 80,
"density": {
"enable": true,
"value_area": 800
}
},
"color": {
"value": "#ffffff"
},
"shape": {
"type": "circle",
"stroke": {
"width": 0,
"color": "#000000"
},
"polygon": {
"nb_sides": 5
},
"image": {
"src":
…Now, how does one go about implementing this awesome library into one's Nuxt project? Sure, there are at least a few Vue libraries that work with Particles, but I was able to hack together a complete component without using any other libraries.
Here's the Code
In its entirety, this is my implementation, inspired by https://www.npmjs.com/package/vue-particles-generator and https://github.com/creotip/vue-particles.
<template>
<div
:id="id"
class="particles-js"
:color="color"
:particleOpacity="particleOpacity"
:linesColor="linesColor"
:particlesNumber="particlesNumber"
:shapeType="shapeType"
:particleSize="particleSize"
:linesWidth="linesWidth"
:lineLinked="lineLinked"
:lineOpacity="lineOpacity"
:linesDistance="linesDistance"
:moveSpeed="moveSpeed"
:movementDirection="movementDirection"
:hoverEffect="hoverEffect"
:hoverMode="hoverMode"
:clickEffect="clickEffect"
:clickMode="clickMode"
></div>
</template>
<script>
/* eslint-disable */
export default {
props: {
color: {
type: String,
default: '#dedede'
},
particleOpacity: {
type: Number,
default: 1.0
},
particlesNumber: {
type: Number,
default: 80
},
shapeType: {
type: String,
default: 'circle'
},
particleSize: {
type: Number,
default: 4
},
linesColor: {
type: String,
default: '#dedede'
},
linesWidth: {
type: Number,
default: 1
},
lineLinked: {
type: Boolean,
default: true
},
lineOpacity: {
type: Number,
default: 0.4
},
linesDistance: {
type: Number,
default: 150
},
moveSpeed: {
type: Number,
default: 3
},
movementDirection: {
type: String,
default: 'bottom-left'
},
hoverEffect: {
type: Boolean,
default: false
},
hoverMode: {
type: String,
default: 'grab'
},
clickEffect: {
type: Boolean,
default: false
},
clickMode: {
type: String,
default: 'push'
}
},
data () {
return {
id: 'particles-instance-' + Math.floor(Math.random() * 5000)
}
},
mounted () {
require('particles.js')
this.$nextTick(() => {
this.initParticleJS(
this.color,
this.particleOpacity,
this.particlesNumber,
this.shapeType,
this.particleSize,
this.linesColor,
this.linesWidth,
this.lineLinked,
this.lineOpacity,
this.linesDistance,
this.moveSpeed,
this.movementDirection,
this.hoverEffect,
this.hoverMode,
this.clickEffect,
this.clickMode
)
})
},
methods: {
initParticleJS (
color,
particleOpacity,
particlesNumber,
shapeType,
particleSize,
linesColor,
linesWidth,
lineLinked,
lineOpacity,
linesDistance,
moveSpeed,
movementDirection,
hoverEffect,
hoverMode,
clickEffect,
clickMode
) {
particlesJS(this.id, {
"particles": {
"number": {
"value": particlesNumber,
"density": {
"enable": true,
"value_area": 800
}
},
"color": {
"value": color
},
"shape": {
// circle, edge, triangle, polygon, star, image
"type": shapeType,
"stroke": {
"width": 0,
"color": "#192231"
},
"polygon": {
"nb_sides": 5
}
},
"opacity": {
"value": particleOpacity,
"random": false,
"anim": {
"enable": false,
"speed": 1,
"opacity_min": 0.1,
"sync": false
}
},
"size": {
"value": particleSize,
"random": true,
"anim": {
"enable": false,
"speed": 40,
"size_min": 0.1,
"sync": false
}
},
"line_linked": {
"enable": lineLinked,
"distance": linesDistance,
"color": linesColor,
"opacity": lineOpacity,
"width": linesWidth
},
"move": {
"enable": true,
"speed": moveSpeed,
"direction": movementDirection,
"random": false,
"straight": false,
"out_mode": "out",
"bounce": false,
"attract": {
"enable": false,
"rotateX": 600,
"rotateY": 1200
}
}
},
"interactivity": {
"detect_on": "canvas",
"events": {
"onhover": {
"enable": hoverEffect,
"mode": hoverMode
},
"onclick": {
"enable": clickEffect,
"mode": clickMode
},
"onresize": {
"enable": true,
"density_auto": true,
"density_area": 400
}
},
"modes": {
"grab": {
"distance": 140,
"line_linked": {
"opacity": 1
}
},
"bubble": {
"distance": 400,
"size": 40,
"duration": 2,
"opacity": 8,
"speed": 3
},
"repulse": {
"distance": 200,
"duration": 0.4
},
"push": {
"particles_nb": 4
},
"remove": {
"particles_nb": 2
}
}
},
"retina_detect": true
})
}
}
}
</script>
Well, that was a doozy! Anyway, to use it, do something like this (don't miss the <client-only></client-only>
:
<template>
<!-- -->
<client-only>
<Particles
color="#DCBA8F"
:particles-number="100"
shape-type="star"
:particle-size="3"
movement-direction="top"
lines-color="#dedede"
:line-linked="false"
:move-speed="0.75"
/>
</client-only>
<!-- -->
</template>
<script>
import Particles from '~/components/Particles.vue'
export default {
components: {
Particles
}
}
</script>
<style lang="scss">
div[id^="particles-instance-"] {
height: 100vh !important;
width: 100vw !important;
position: fixed !important;
top: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
background: rgba($color: #05114e, $alpha: 0.4);
z-index: 2 !important;
}
</style>
The above code gives you a fullscreen particles background. Mixed with something like this (with a background of ~assets/img/background.png
):
.hero-background {
height: 100vh !important;
width: 100vw !important;
position: fixed !important;
top: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
background-size: cover !important;
background-repeat: no-repeat !important;
background-blend-mode: overlay !important;
background-attachment: fixed !important;
background-position: fixed !important;
background: rgba($color: #05114e, $alpha: 0.4);
background-image: url("~assets/img/background.png") !important;
z-index: 1 !important;
}
you'd get a nice overlay. There are a ton of options, really; it's all CSS past this point. https://vincentgarreau.com/particles.js/ is your friend when it comes to checking out what changing props does.
Hope this was helpful; enjoy! Stay safe and keep on coding!
Top comments (2)
Hey, all; bit of an update here - make sure you wrap any Particles components in a
<client-only></client-only>
or it won't work; I've updated the article, too.that's so great. this content was the only thing I can found about particles in nuxt.