feat: 实现墨丝效果,spreading阶段粒子间绘制渐变曲线连线

This commit is contained in:
张翔
2026-05-03 19:46:59 +08:00
parent 14f16ed794
commit 4ca3eb6c92
+63
View File
@@ -465,6 +465,67 @@ function drawParticle(
}
}
function drawInkStrings(
ctx: CanvasRenderingContext2D,
particles: Particle[],
config: ResponsiveConfig,
): void {
const spreading = particles.filter(
p => p.phase === 'spreading' && p.age >= p.delay
);
if (spreading.length < 2) {
return;
}
const threshold = config.connectionDistance * config.inkStringThreshold;
ctx.save();
ctx.lineCap = 'round';
for (let i = 0; i < spreading.length; i++) {
const a = spreading[i];
if (!a) {
continue;
}
for (let j = i + 1; j < spreading.length; j++) {
const b = spreading[j];
if (!b) {
continue;
}
const dx = a.x - b.x;
const dy = a.y - b.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < threshold && dist > 0) {
const distRatio = 1 - dist / threshold;
const alpha = distRatio * 0.15 * Math.min(a.opacity, b.opacity);
const useAccent = ACCENT_TONES.includes(a.toneIndex) || ACCENT_TONES.includes(b.toneIndex);
const rgb = useAccent ? TONES[3].rgb : TONES[0].rgb;
const mx = (a.x + b.x) / 2;
const my = (a.y + b.y) / 2;
const perpX = -dy / dist;
const perpY = dx / dist;
const curvature = (Math.random() - 0.5) * dist * 0.2;
const cpx = mx + perpX * curvature;
const cpy = my + perpY * curvature;
const grad = ctx.createLinearGradient(a.x, a.y, b.x, b.y);
grad.addColorStop(0, `rgba(${rgb}, ${alpha * 0.3})`);
grad.addColorStop(0.5, `rgba(${rgb}, ${alpha})`);
grad.addColorStop(1, `rgba(${rgb}, ${alpha * 0.3})`);
ctx.beginPath();
ctx.moveTo(a.x, a.y);
ctx.quadraticCurveTo(cpx, cpy, b.x, b.y);
ctx.strokeStyle = grad;
ctx.lineWidth = Math.max(0.2, distRatio * 1.5);
ctx.stroke();
}
}
}
ctx.restore();
}
function drawConnections(
ctx: CanvasRenderingContext2D,
particles: Particle[],
@@ -683,6 +744,7 @@ export function InkDataMorph({
}
drawConnections(ctx, finalParticles, config.connectionDistance);
drawInkStrings(ctx, finalParticles, config);
}, []);
useEffect(() => {
@@ -746,6 +808,7 @@ export function InkDataMorph({
}
drawConnections(ctx, particles, config.connectionDistance);
drawInkStrings(ctx, particles, config);
if (allComplete) {
animationRef.current = undefined;