UNPKG

tsparticles

Version:

Easily create highly customizable particle animations and use them as animated backgrounds for your website. Ready to use components available also for React, Vue.js (2.x and 3.x), Angular, Svelte, jQuery, Preact, Riot.js, Inferno.

157 lines (156 loc) 6.96 kB
import { NumberUtils, Plugins, Utils } from "../../Utils"; import { HoverMode } from "../../Enums"; export class Mover { constructor(container, particle) { this.container = container; this.particle = particle; } move(delta) { const particle = this.particle; particle.bubble.inRange = false; particle.links = []; for (const [, plugin] of this.container.plugins) { if (particle.destroyed) { break; } if (plugin.particleUpdate) { plugin.particleUpdate(particle, delta); } } if (particle.destroyed) { return; } this.moveParticle(delta); this.moveParallax(); } moveParticle(delta) { var _a, _b; const particle = this.particle; const particlesOptions = particle.options; if (!particlesOptions.move.enable) { return; } const container = this.container; const slowFactor = this.getProximitySpeedFactor(); const baseSpeed = ((_a = particle.moveSpeed) !== null && _a !== void 0 ? _a : NumberUtils.getRangeValue(particle.options.move.speed) * container.retina.pixelRatio) * container.retina.reduceFactor; const maxSize = NumberUtils.getRangeMax(particle.options.size.value) * container.retina.pixelRatio; const sizeFactor = particlesOptions.move.size ? particle.getRadius() / maxSize : 1; const moveSpeed = (baseSpeed / 2) * sizeFactor * slowFactor * delta.factor; const moveDrift = (_b = particle.moveDrift) !== null && _b !== void 0 ? _b : NumberUtils.getRangeValue(particle.options.move.drift) * container.retina.pixelRatio; this.applyPath(delta); const gravityOptions = particlesOptions.move.gravity; if (gravityOptions.enable) { particle.velocity.y += (gravityOptions.acceleration * delta.factor) / (60 * moveSpeed); } particle.velocity.x += (moveDrift * delta.factor) / (60 * moveSpeed); const decay = 1 - particle.options.move.decay; particle.velocity.multTo(decay); const velocity = particle.velocity.mult(moveSpeed); if (gravityOptions.enable && velocity.y >= gravityOptions.maxSpeed && gravityOptions.maxSpeed > 0) { velocity.y = gravityOptions.maxSpeed; particle.velocity.y = velocity.y / moveSpeed; } particle.position.addTo(velocity); if (particlesOptions.move.vibrate) { particle.position.x += Math.sin(particle.position.x * Math.cos(particle.position.y)); particle.position.y += Math.cos(particle.position.y * Math.sin(particle.position.x)); } const initialPosition = particle.initialPosition; const initialDistance = NumberUtils.getDistance(initialPosition, particle.position); if (particle.maxDistance) { if (initialDistance >= particle.maxDistance && !particle.misplaced) { particle.misplaced = initialDistance > particle.maxDistance; particle.velocity.x = particle.velocity.y / 2 - particle.velocity.x; particle.velocity.y = particle.velocity.x / 2 - particle.velocity.y; } else if (initialDistance < particle.maxDistance && particle.misplaced) { particle.misplaced = false; } else if (particle.misplaced) { if ((particle.position.x < initialPosition.x && particle.velocity.x < 0) || (particle.position.x > initialPosition.x && particle.velocity.x > 0)) { particle.velocity.x *= -Math.random(); } if ((particle.position.y < initialPosition.y && particle.velocity.y < 0) || (particle.position.y > initialPosition.y && particle.velocity.y > 0)) { particle.velocity.y *= -Math.random(); } } } } applyPath(delta) { const particle = this.particle; const particlesOptions = particle.options; const pathOptions = particlesOptions.move.path; const pathEnabled = pathOptions.enable; if (!pathEnabled) { return; } const container = this.container; if (particle.lastPathTime <= particle.pathDelay) { particle.lastPathTime += delta.value; return; } let generator = container.pathGenerator; if (pathOptions.generator) { const customGenerator = Plugins.getPathGenerator(pathOptions.generator); if (customGenerator) { generator = customGenerator; } } const path = generator.generate(particle); particle.velocity.addTo(path); if (pathOptions.clamp) { particle.velocity.x = NumberUtils.clamp(particle.velocity.x, -1, 1); particle.velocity.y = NumberUtils.clamp(particle.velocity.y, -1, 1); } particle.lastPathTime -= particle.pathDelay; } moveParallax() { const container = this.container; const options = container.actualOptions; if (Utils.isSsr() || !options.interactivity.events.onHover.parallax.enable) { return; } const particle = this.particle; const parallaxForce = options.interactivity.events.onHover.parallax.force; const mousePos = container.interactivity.mouse.position; if (!mousePos) { return; } const canvasCenter = { x: container.canvas.size.width / 2, y: container.canvas.size.height / 2, }; const parallaxSmooth = options.interactivity.events.onHover.parallax.smooth; const factor = particle.getRadius() / parallaxForce; const tmp = { x: (mousePos.x - canvasCenter.x) * factor, y: (mousePos.y - canvasCenter.y) * factor, }; particle.offset.x += (tmp.x - particle.offset.x) / parallaxSmooth; particle.offset.y += (tmp.y - particle.offset.y) / parallaxSmooth; } getProximitySpeedFactor() { const container = this.container; const options = container.actualOptions; const active = Utils.isInArray(HoverMode.slow, options.interactivity.events.onHover.mode); if (!active) { return 1; } const mousePos = this.container.interactivity.mouse.position; if (!mousePos) { return 1; } const particlePos = this.particle.getPosition(); const dist = NumberUtils.getDistance(mousePos, particlePos); const radius = container.retina.slowModeRadius; if (dist > radius) { return 1; } const proximityFactor = dist / radius || 0; const slowFactor = options.interactivity.modes.slow.factor; return proximityFactor / slowFactor; } }