fix: 增强粒子视觉效果——发光粒子+加粗边缘+更高不透明度
- 粒子尺寸3-7px, 红色发光(shadowBlur=6) - 边缘线加粗到1.5-5.5px, 不透明度0.3-0.8 - 粒子生成率提高(4/边/生命周期) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2818,13 +2818,13 @@ function renderTrafficContinuous(totalSpan, minTs, maxTs) {
|
||||
return pt;
|
||||
};
|
||||
|
||||
// Spawn new particles
|
||||
// Spawn new particles — higher rate for denser visual
|
||||
const now = _trafficCurrentTime;
|
||||
const particleLifetime = Math.max(3, Math.min(8, totalSpan * 0.1));
|
||||
const spawnInterval = Math.max(0.02, particleLifetime / 8); // spawn ~8 particles per edge per lifetime
|
||||
const particleLifetime = Math.max(4, Math.min(10, totalSpan * 0.15));
|
||||
const spawnRate = Math.max(0.03, particleLifetime / 4); // 4 particles per edge per lifetime
|
||||
activeEdges.forEach(e => {
|
||||
const key = e.source + '|' + e.target;
|
||||
if (!_trafficSpawnTimers[key] || now - _trafficSpawnTimers[key] > spawnInterval / Math.max(1, e.count)) {
|
||||
if (!_trafficSpawnTimers[key] || now - _trafficSpawnTimers[key] > spawnRate) {
|
||||
_trafficSpawnTimers[key] = now;
|
||||
_trafficParticles.push({
|
||||
source: e.source, target: e.target,
|
||||
@@ -2835,10 +2835,10 @@ function renderTrafficContinuous(totalSpan, minTs, maxTs) {
|
||||
}
|
||||
});
|
||||
|
||||
// Update & render particles
|
||||
// Update & render particles — bright, visible dots
|
||||
const toRemove = [];
|
||||
_trafficParticles.forEach((p, i) => {
|
||||
p.progress += p.speed * Math.min(0.1, (1 / 60) * _trafficSpeed * 2);
|
||||
p.progress += p.speed * (1/60) * _trafficSpeed * 3;
|
||||
if (p.progress >= 1) { toRemove.push(i); return; }
|
||||
|
||||
const srcC = coords[p.source]; const dstC = coords[p.target];
|
||||
@@ -2848,33 +2848,35 @@ function renderTrafficContinuous(totalSpan, minTs, maxTs) {
|
||||
if (!p1 || !p2) { toRemove.push(i); return; }
|
||||
|
||||
const midX = (p1.x + p2.x) / 2;
|
||||
const midY = (p1.y + p2.y) / 2 - Math.abs(p2.x - p1.x) * 0.1;
|
||||
const midY = (p1.y + p2.y) / 2 - Math.abs(p2.x - p1.x) * 0.12;
|
||||
|
||||
// Fade trail
|
||||
const t = p.progress;
|
||||
const px = (1-t)*(1-t)*p1.x + 2*(1-t)*t*midX + t*t*p2.x;
|
||||
const py = (1-t)*(1-t)*p1.y + 2*(1-t)*t*midY + t*t*p2.y;
|
||||
|
||||
const size = 2 + 2.5 * (p.count / maxCount);
|
||||
const alpha = 0.5 + 0.5 * (1 - Math.abs(t - 0.5) * 2); // brightest at midpoint
|
||||
const size = 3 + 4 * (p.count / maxCount);
|
||||
// Glow
|
||||
_trafficCanvasCtx.shadowColor = 'rgba(230,57,70,0.8)';
|
||||
_trafficCanvasCtx.shadowBlur = 6;
|
||||
_trafficCanvasCtx.beginPath();
|
||||
_trafficCanvasCtx.arc(px, py, size, 0, Math.PI * 2);
|
||||
_trafficCanvasCtx.fillStyle = `rgba(230,57,70,${alpha.toFixed(2)})`;
|
||||
_trafficCanvasCtx.fillStyle = '#ff4444';
|
||||
_trafficCanvasCtx.fill();
|
||||
_trafficCanvasCtx.shadowBlur = 0;
|
||||
});
|
||||
for (let i = toRemove.length - 1; i >= 0; i--) _trafficParticles.splice(toRemove[i], 1);
|
||||
|
||||
// Draw active edge traces (faint background)
|
||||
activeEdges.forEach(e => {
|
||||
// Draw active edge traces (background lines)
|
||||
activeEdges.slice(0, 200).forEach(e => {
|
||||
const srcC = coords[e.source]; const dstC = coords[e.target];
|
||||
if (!srcC || !dstC) return;
|
||||
const p1 = getPixel(e.source, srcC[0], srcC[1]);
|
||||
const p2 = getPixel(e.target, dstC[0], dstC[1]);
|
||||
if (!p1 || !p2) return;
|
||||
const midX = (p1.x + p2.x) / 2;
|
||||
const midY = (p1.y + p2.y) / 2 - Math.abs(p2.x - p1.x) * 0.1;
|
||||
const alpha = 0.15 + 0.3 * (e.count / maxCount);
|
||||
const width = 0.8 + 2 * (e.count / maxCount);
|
||||
const midY = (p1.y + p2.y) / 2 - Math.abs(p2.x - p1.x) * 0.12;
|
||||
const alpha = 0.3 + 0.5 * (e.count / maxCount);
|
||||
const width = 1.5 + 4 * (e.count / maxCount);
|
||||
_trafficCanvasCtx.beginPath();
|
||||
_trafficCanvasCtx.moveTo(p1.x, p1.y);
|
||||
_trafficCanvasCtx.quadraticCurveTo(midX, midY, p2.x, p2.y);
|
||||
|
||||
Reference in New Issue
Block a user