feat: 粒子源-目标颜色区分+流速按流量比例

- 边轨迹: linearGradient src青绿→dst红色
- 粒子: src青绿(#2ec4b6)→dst红色(#e63946)渐变
- 粒子速度: speedMul=0.5+1.5*ratio, 高流量边粒子更快
- 粒子数量: 3+6*ratio, 高流量边更多粒子
- 发光增强: shadowBlur=5, opacity=0.6+0.4*weight

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
TianXuan Developer
2026-07-25 10:36:40 +08:00
parent 0c75d986c2
commit 8fbf5be897
@@ -2823,26 +2823,31 @@ function renderTrafficCrossfade() {
const ratio = Math.min(1, e.count / maxCount);
const alpha = 0.4 + 0.6 * e.weight;
// Bezier curve
// Edge trace with source→destination color gradient
const grad = ctx.createLinearGradient(cached.p1x, cached.p1y, cached.p2x, cached.p2y);
grad.addColorStop(0, 'rgba(46,196,182,' + alpha.toFixed(2) + ')'); // src: teal
grad.addColorStop(1, 'rgba(230,57,70,' + alpha.toFixed(2) + ')'); // dst: red
ctx.beginPath();
ctx.moveTo(cached.p1x, cached.p1y);
ctx.quadraticCurveTo(cached.midX, cached.midY, cached.p2x, cached.p2y);
ctx.strokeStyle = 'rgba(67,97,238,' + alpha.toFixed(2) + ')';
ctx.strokeStyle = grad;
ctx.lineWidth = 1.5 + 4 * ratio;
ctx.stroke();
// Particles flowing along curve (Date.now() driven, continuous)
const nP = Math.ceil(3 + 5 * ratio);
// Particles: source(teal)→destination(red), speed ∝ traffic volume
const speedMul = 0.5 + 1.5 * ratio; // higher traffic → faster particles
const nP = Math.ceil(3 + 6 * ratio);
for (let pi = 0; pi < nP; pi++) {
const pt = ((Date.now() / 2000 + pi / nP) % 1);
const pt = ((Date.now() / 2000 * speedMul + pi / nP) % 1);
const px = (1-pt)*(1-pt)*cached.p1x + 2*(1-pt)*pt*cached.midX + pt*pt*cached.p2x;
const py = (1-pt)*(1-pt)*cached.p1y + 2*(1-pt)*pt*cached.midY + pt*pt*cached.p2y;
const r = Math.round(67 + 163*pt), g = Math.round(97 - 40*pt), b = Math.round(238 - 168*pt);
// src teal→dst red gradient
const cr = Math.round(46 + 184*pt), cg = Math.round(196 - 139*pt), cb = Math.round(182 - 112*pt);
ctx.beginPath();
ctx.arc(px, py, 2 + 3*ratio, 0, Math.PI*2);
ctx.fillStyle = 'rgba(' + r + ',' + g + ',' + b + ',' + (0.5+0.5*e.weight) + ')';
ctx.shadowColor = 'rgba(' + r + ',' + g + ',' + b + ',0.5)';
ctx.shadowBlur = 4;
ctx.fillStyle = 'rgba(' + cr + ',' + cg + ',' + cb + ',' + (0.6+0.4*e.weight) + ')';
ctx.shadowColor = 'rgba(' + cr + ',' + cg + ',' + cb + ',0.6)';
ctx.shadowBlur = 5;
ctx.fill();
ctx.shadowBlur = 0;
}