feat: 实现飞白笔触效果,settling阶段根据速度方向绘制墨迹拖尾
This commit is contained in:
@@ -189,6 +189,8 @@ function updateParticle(p: Particle, maxTrail: number): void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
p.prevVx = p.vx;
|
||||||
|
p.prevVy = p.vy;
|
||||||
p.x += p.vx;
|
p.x += p.vx;
|
||||||
p.y += p.vy;
|
p.y += p.vy;
|
||||||
p.vx *= 0.98;
|
p.vx *= 0.98;
|
||||||
@@ -377,6 +379,43 @@ function drawInkLayers(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function drawFeibai(
|
||||||
|
ctx: CanvasRenderingContext2D,
|
||||||
|
p: Particle,
|
||||||
|
rgb: string,
|
||||||
|
): void {
|
||||||
|
const speed = Math.sqrt(p.prevVx * p.prevVx + p.prevVy * p.prevVy);
|
||||||
|
if (speed < 0.1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dirX = -p.prevVx / speed;
|
||||||
|
const dirY = -p.prevVy / speed;
|
||||||
|
const length = p.radius * (3 + Math.random() * 2);
|
||||||
|
const endX = p.x + dirX * length;
|
||||||
|
const endY = p.y + dirY * length;
|
||||||
|
|
||||||
|
const perpX = -dirY;
|
||||||
|
const perpY = dirX;
|
||||||
|
const curvature = (Math.random() - 0.5) * length * 0.15;
|
||||||
|
const cpX = (p.x + endX) / 2 + perpX * curvature;
|
||||||
|
const cpY = (p.y + endY) / 2 + perpY * curvature;
|
||||||
|
|
||||||
|
const grad = ctx.createLinearGradient(p.x, p.y, endX, endY);
|
||||||
|
grad.addColorStop(0, `rgba(${rgb}, ${p.opacity * 0.25})`);
|
||||||
|
grad.addColorStop(1, 'transparent');
|
||||||
|
|
||||||
|
ctx.save();
|
||||||
|
ctx.lineCap = 'round';
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(p.x, p.y);
|
||||||
|
ctx.quadraticCurveTo(cpX, cpY, endX, endY);
|
||||||
|
ctx.strokeStyle = grad;
|
||||||
|
ctx.lineWidth = Math.max(0.3, p.radius * 0.6);
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.restore();
|
||||||
|
}
|
||||||
|
|
||||||
function drawParticle(
|
function drawParticle(
|
||||||
ctx: CanvasRenderingContext2D,
|
ctx: CanvasRenderingContext2D,
|
||||||
p: Particle,
|
p: Particle,
|
||||||
@@ -400,6 +439,9 @@ function drawParticle(
|
|||||||
drawInkLayers(ctx, p, config);
|
drawInkLayers(ctx, p, config);
|
||||||
} else if (p.phase === 'settling') {
|
} else if (p.phase === 'settling') {
|
||||||
drawInkLayers(ctx, p, config);
|
drawInkLayers(ctx, p, config);
|
||||||
|
if (config.showFeibai) {
|
||||||
|
drawFeibai(ctx, p, rgb);
|
||||||
|
}
|
||||||
} else if (p.phase === 'fading') {
|
} else if (p.phase === 'fading') {
|
||||||
const grad1 = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, r * 1.5);
|
const grad1 = ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, r * 1.5);
|
||||||
grad1.addColorStop(0, `rgba(${rgb}, ${p.opacity * 0.6})`);
|
grad1.addColorStop(0, `rgba(${rgb}, ${p.opacity * 0.6})`);
|
||||||
|
|||||||
Reference in New Issue
Block a user