@tsparticles/effect-trail
Version:
tsParticles trail effect
136 lines (130 loc) • 10.4 kB
JavaScript
(function(g){g.__tsParticlesInternals=g.__tsParticlesInternals||{};g.__tsParticlesInternals.bundles=g.__tsParticlesInternals.bundles||{};g.__tsParticlesInternals.effects=g.__tsParticlesInternals.effects||{};g.__tsParticlesInternals.engine=g.__tsParticlesInternals.engine||{};g.__tsParticlesInternals.interactions=g.__tsParticlesInternals.interactions||{};g.__tsParticlesInternals.palettes=g.__tsParticlesInternals.palettes||{};g.__tsParticlesInternals.paths=g.__tsParticlesInternals.paths||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins=g.__tsParticlesInternals.plugins||{};g.__tsParticlesInternals.plugins.emittersShapes=g.__tsParticlesInternals.plugins.emittersShapes||{};g.__tsParticlesInternals.presets=g.__tsParticlesInternals.presets||{};g.__tsParticlesInternals.shapes=g.__tsParticlesInternals.shapes||{};g.__tsParticlesInternals.updaters=g.__tsParticlesInternals.updaters||{};g.__tsParticlesInternals.utils=g.__tsParticlesInternals.utils||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas=g.__tsParticlesInternals.canvas||{};g.__tsParticlesInternals.canvas.utils=g.__tsParticlesInternals.canvas.utils||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path=g.__tsParticlesInternals.path||{};g.__tsParticlesInternals.path.utils=g.__tsParticlesInternals.path.utils||{};var __tsProxyFactory=typeof Proxy!=="undefined"?function(obj){return new Proxy(obj,{get:function(target,key){if(!(key in target)){target[key]={};}return target[key];}});}:function(obj){return obj;};g.__tsParticlesInternals.bundles=__tsProxyFactory(g.__tsParticlesInternals.bundles);g.__tsParticlesInternals.effects=__tsProxyFactory(g.__tsParticlesInternals.effects);g.__tsParticlesInternals.interactions=__tsProxyFactory(g.__tsParticlesInternals.interactions);g.__tsParticlesInternals.palettes=__tsProxyFactory(g.__tsParticlesInternals.palettes);g.__tsParticlesInternals.paths=__tsProxyFactory(g.__tsParticlesInternals.paths);g.__tsParticlesInternals.plugins=__tsProxyFactory(g.__tsParticlesInternals.plugins);g.__tsParticlesInternals.plugins.emittersShapes=__tsProxyFactory(g.__tsParticlesInternals.plugins.emittersShapes);g.__tsParticlesInternals.presets=__tsProxyFactory(g.__tsParticlesInternals.presets);g.__tsParticlesInternals.shapes=__tsProxyFactory(g.__tsParticlesInternals.shapes);g.__tsParticlesInternals.updaters=__tsProxyFactory(g.__tsParticlesInternals.updaters);g.__tsParticlesInternals.utils=__tsProxyFactory(g.__tsParticlesInternals.utils);g.__tsParticlesInternals.canvas=__tsProxyFactory(g.__tsParticlesInternals.canvas);g.__tsParticlesInternals.path=__tsProxyFactory(g.__tsParticlesInternals.path);g.tsparticlesInternalExports=g.tsparticlesInternalExports||{};})(typeof globalThis!=="undefined"?globalThis:typeof window!=="undefined"?window:this);
/* Effect v4.3.2 */
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@tsparticles/engine')) :
typeof define === 'function' && define.amd ? define(['exports', '@tsparticles/engine'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.__tsParticlesInternals = global.__tsParticlesInternals || {}, global.__tsParticlesInternals.effects = global.__tsParticlesInternals.effects || {}, global.__tsParticlesInternals.effects.trail = global.__tsParticlesInternals.effects.trail || {}), global.__tsParticlesInternals.engine));
})(this, (function (exports, engine) { 'use strict';
const minTrailLength = 3, trailLengthOffset = 1, minWidth = -1, firstIndex = 0, defaultLength = 10, loopTrailLengthOffset = 2, loopTrailLengthMinIndex = 0, defaultWidth = 0, minBound = 0;
const defaultTransform = {
a: 1,
b: 0,
c: 0,
d: 1,
};
class TrailDrawer {
#container;
constructor(container) {
this.#container = container;
}
drawAfter(data) {
const { context, drawPosition, drawRadius, drawScale, particle, transformData } = data, container = this.#container, diameter = drawRadius * engine.double, pxRatio = container.retina.pixelRatio, trail = particle.trail;
if (!trail || !particle.trailLength) {
return;
}
const currentPos = drawPosition, pathLength = particle.trailLength * drawScale + drawRadius;
trail.push({
break: particle.justWarped,
color: context.fillStyle || context.strokeStyle,
position: {
x: currentPos.x,
y: currentPos.y,
},
transformData,
});
if (trail.length < minTrailLength) {
return;
}
const pathLengthFloor = Math.floor(pathLength);
if (trail.length > pathLengthFloor) {
trail.splice(firstIndex, trail.length - pathLengthFloor);
}
const trailLength = Math.min(trail.length, pathLength);
context.save();
context.lineCap = "butt";
context.lineJoin = "round";
for (let i = trailLength - loopTrailLengthOffset; i > loopTrailLengthMinIndex; i--) {
const previousStep = trail[i + trailLengthOffset], step = trail[i], nextStep = trail[i - trailLengthOffset];
if (!previousStep || !step || !nextStep) {
continue;
}
const previousPosition = previousStep.position, position = step.position, nextPosition = nextStep.position, stepTransformData = particle.trailTransform ? (step.transformData ?? defaultTransform) : defaultTransform;
if (step.break || previousStep.break || nextStep.break) {
continue;
}
context.setTransform(stepTransformData.a, stepTransformData.b, stepTransformData.c, stepTransformData.d, position.x, position.y);
const startX = (previousPosition.x + position.x) * engine.half - position.x, startY = (previousPosition.y + position.y) * engine.half - position.y, endX = (position.x + nextPosition.x) * engine.half - position.x, endY = (position.y + nextPosition.y) * engine.half - position.y;
context.beginPath();
context.moveTo(startX, startY);
context.quadraticCurveTo(engine.originPoint.x, engine.originPoint.y, endX, endY);
const width = Math.max((i / trailLength) * diameter, pxRatio, (particle.trailMinWidth ?? minWidth) * drawScale), oldAlpha = context.globalAlpha;
context.globalAlpha = particle.trailFade ? i / trailLength : engine.defaultAlpha;
context.lineWidth = particle.trailMaxWidth ? Math.min(width, particle.trailMaxWidth * drawScale) : width;
context.strokeStyle = step.color;
context.stroke();
context.globalAlpha = oldAlpha;
}
context.restore();
}
isInsideCanvas(data) {
const { canvasSize, direction, outMode, particle, radius } = data, position = particle.position, trail = particle.trail;
let minX = position.x - radius, maxX = position.x + radius, minY = position.y - radius, maxY = position.y + radius;
if (trail?.length) {
const widthPadding = Math.max(radius, particle.trailMaxWidth ?? defaultWidth, particle.trailMinWidth ?? defaultWidth);
for (const step of trail) {
minX = Math.min(minX, step.position.x - widthPadding);
maxX = Math.max(maxX, step.position.x + widthPadding);
minY = Math.min(minY, step.position.y - widthPadding);
maxY = Math.max(maxY, step.position.y + widthPadding);
}
}
const strictBounds = outMode === engine.OutMode.destroy;
if (direction === engine.OutModeDirection.bottom) {
return minY <= canvasSize.height;
}
if (direction === engine.OutModeDirection.left) {
return maxX >= minBound;
}
if (direction === engine.OutModeDirection.right) {
return minX <= canvasSize.width;
}
if (direction === engine.OutModeDirection.top) {
return maxY >= minBound;
}
if (!strictBounds) {
return (position.x + radius >= minBound &&
position.y + radius >= minBound &&
position.x - radius <= canvasSize.width &&
position.y - radius <= canvasSize.height);
}
return maxX >= minBound && maxY >= minBound && minX <= canvasSize.width && minY <= canvasSize.height;
}
particleInit(container, particle) {
particle.trail = [];
const effectData = particle.effectData;
particle.trailFade = effectData?.fade ?? true;
particle.trailLength = engine.getRangeValue(effectData?.length ?? defaultLength) * container.retina.pixelRatio;
particle.trailMaxWidth = effectData?.maxWidth
? engine.getRangeValue(effectData.maxWidth) * container.retina.pixelRatio
: undefined;
particle.trailMinWidth = effectData?.minWidth
? engine.getRangeValue(effectData.minWidth) * container.retina.pixelRatio
: undefined;
particle.trailTransform = effectData?.transform ?? false;
}
}
async function loadTrailEffect(engine) {
engine.checkVersion("4.3.2");
await engine.pluginManager.register(e => {
e.pluginManager.addEffect("trail", container => {
return Promise.resolve(new TrailDrawer(container));
});
});
}
const globalObject = globalThis;
globalObject.__tsParticlesInternals = globalObject.__tsParticlesInternals ?? {};
globalObject.loadTrailEffect = loadTrailEffect;
exports.loadTrailEffect = loadTrailEffect;
}));
Object.assign(globalThis.window || globalThis, { loadTrailEffect: (globalThis.__tsParticlesInternals.effects.trail || {}).loadTrailEffect });
delete (globalThis.window || globalThis).tsparticlesInternalExports;