收口聊天室安全边界并优化特效生命周期

This commit is contained in:
2026-04-25 02:52:30 +08:00
parent 4d3f4f7a4b
commit 855d031b04
26 changed files with 1219 additions and 175 deletions
+26 -12
View File
@@ -87,7 +87,7 @@ const LightningEffect = (() => {
* @param {HTMLCanvasElement} canvas
* @param {CanvasRenderingContext2D} ctx
*/
function _flash(canvas, ctx) {
function _flash(canvas, ctx, timers) {
const w = canvas.width;
const h = canvas.height;
@@ -122,16 +122,16 @@ const LightningEffect = (() => {
}
// 短促残影:闪电消失后保留一层很淡的余辉,避免“闪一下就没了”。
setTimeout(() => {
timers.push(setTimeout(() => {
ctx.clearRect(0, 0, w, h);
_drawStormGlow(canvas, ctx);
ctx.fillStyle = "rgba(185, 205, 255, 0.12)";
ctx.fillRect(0, 0, w, h);
}, 90);
}, 90));
setTimeout(() => {
timers.push(setTimeout(() => {
ctx.clearRect(0, 0, w, h);
}, 190);
}, 190));
}
/**
@@ -146,6 +146,7 @@ const LightningEffect = (() => {
const DURATION = 7600;
let count = 0;
let finished = false;
const timers = [];
/**
* 统一结束特效,避免多次触发 onEnd。
@@ -156,6 +157,7 @@ const LightningEffect = (() => {
}
finished = true;
timers.forEach((timer) => clearTimeout(timer));
ctx.clearRect(0, 0, canvas.width, canvas.height);
onEnd();
}
@@ -163,29 +165,41 @@ const LightningEffect = (() => {
// 间隔不规则触发多次闪电(模拟真实雷电节奏)
function nextFlash() {
if (count >= FLASHES) {
setTimeout(() => {
timers.push(setTimeout(() => {
finish();
}, 520);
}, 520));
return;
}
_flash(canvas, ctx);
_flash(canvas, ctx, timers);
count++;
// 让雷电节奏有“成组爆发”的感觉:有时连续两下,有时间隔更久。
const delay = Math.random() > 0.65
? 140 + Math.random() * 140
: 420 + Math.random() * 520;
setTimeout(nextFlash, delay);
timers.push(setTimeout(nextFlash, delay));
}
// 短暂延迟后开始第一次闪电
setTimeout(nextFlash, 300);
timers.push(setTimeout(nextFlash, 300));
// 安全兜底:超时强制结束
setTimeout(() => {
timers.push(setTimeout(() => {
finish();
}, DURATION + 500);
}, DURATION + 500));
return {
cancel() {
if (finished) {
return;
}
finished = true;
timers.forEach((timer) => clearTimeout(timer));
ctx.clearRect(0, 0, canvas.width, canvas.height);
},
};
}
return { start };