@tsparticles/effect-trail
Version:
tsParticles trail effect
76 lines (75 loc) • 3.79 kB
JavaScript
import { defaultAlpha, double, getRangeValue, half, none, originPoint, } from "@tsparticles/engine";
const minTrailLength = 2, trailLengthOffset = 1, minWidth = -1, defaultLength = 10;
const defaultTransform = {
a: 1,
b: 0,
c: 0,
d: 1,
};
export class TrailDrawer {
draw(data) {
const { context, radius, particle, transformData } = data, diameter = radius * double, pxRatio = particle.container.retina.pixelRatio, currentPos = particle.getPosition(), trail = particle.trail;
if (!trail || !particle.trailLength) {
return;
}
const pathLength = particle.trailLength + radius;
trail.push({
color: context.fillStyle ?? context.strokeStyle,
position: {
x: currentPos.x,
y: currentPos.y,
},
transformData: { ...data.transformData },
});
if (trail.length < minTrailLength) {
return;
}
while (trail.length > pathLength) {
trail.shift();
}
const trailLength = Math.min(trail.length, pathLength), canvasSize = {
width: particle.container.canvas.size.width + diameter,
height: particle.container.canvas.size.height + diameter,
};
let lastPos = trail[trailLength - trailLengthOffset].position;
for (let i = trailLength; i > none; i--) {
const step = trail[i - trailLengthOffset], position = step.position, stepTransformData = particle.trailTransform
? (step.transformData ?? defaultTransform)
: defaultTransform;
context.setTransform(stepTransformData.a, stepTransformData.b, stepTransformData.c, stepTransformData.d, position.x, position.y);
context.beginPath();
context.moveTo(lastPos.x - position.x, lastPos.y - position.y);
const warp = {
x: (lastPos.x + canvasSize.width) % canvasSize.width,
y: (lastPos.y + canvasSize.height) % canvasSize.height,
};
if (Math.abs(lastPos.x - position.x) > canvasSize.width * half ||
Math.abs(lastPos.y - position.y) > canvasSize.height * half) {
lastPos = position;
continue;
}
context.lineTo(Math.abs(lastPos.x - position.x) > canvasSize.width * half ? warp.x : originPoint.x, Math.abs(lastPos.y - position.y) > canvasSize.height * half ? warp.y : originPoint.y);
const width = Math.max((i / trailLength) * diameter, pxRatio, particle.trailMinWidth ?? minWidth), oldAlpha = context.globalAlpha;
context.globalAlpha = particle.trailFade ? i / trailLength : defaultAlpha;
context.lineWidth = particle.trailMaxWidth ? Math.min(width, particle.trailMaxWidth) : width;
context.strokeStyle = step.color;
context.stroke();
context.globalAlpha = oldAlpha;
lastPos = position;
}
context.setTransform(transformData.a, transformData.b, transformData.c, transformData.d, currentPos.x, currentPos.y);
}
particleInit(container, particle) {
particle.trail = [];
const effectData = particle.effectData;
particle.trailFade = effectData?.fade ?? true;
particle.trailLength = getRangeValue(effectData?.length ?? defaultLength) * container.retina.pixelRatio;
particle.trailMaxWidth = effectData?.maxWidth
? getRangeValue(effectData.maxWidth) * container.retina.pixelRatio
: undefined;
particle.trailMinWidth = effectData?.minWidth
? getRangeValue(effectData.minWidth) * container.retina.pixelRatio
: undefined;
particle.trailTransform = effectData?.transform ?? false;
}
}