diff --git a/plugin/contents/ui/dancer.html b/plugin/contents/ui/dancer.html
index 53eb3d3..16caced 100644
--- a/plugin/contents/ui/dancer.html
+++ b/plugin/contents/ui/dancer.html
@@ -1802,7 +1802,15 @@ globeCanvas.style.cssText =
'opacity:0;transition:opacity 1.5s ease;';
sunEl.appendChild(globeCanvas);
const gctx = globeCanvas.getContext('2d');
-let globeRot = 0, lastGlobeTs = 0;
+let globeRot = 0, lastGlobeTs = 0, globeLoopOn = false;
+
+/* Loop roda só enquanto o globo é visível — dorme quando baladaAmt zera */
+function startGlobeLoop() {
+ if (globeLoopOn) return;
+ globeLoopOn = true;
+ lastGlobeTs = 0;
+ requestAnimationFrame(drawGlobe);
+}
/* 8 luzes nos eixos ortogonais — cobertura 360° garantida.
±Y não são afetados pelo lrot, ±X e ±Z orbitam entre si. */
@@ -1818,6 +1826,7 @@ const MIRROR_LIGHTS = [
];
function drawGlobe(ts) {
+ if (!balada && baladaAmt < 0.01) { globeLoopOn = false; lastGlobeTs = 0; return; }
requestAnimationFrame(drawGlobe);
if (baladaAmt < 0.01) { lastGlobeTs = 0; return; }
globeCanvas.style.opacity = chuva ? 0 : baladaAmt;
@@ -1900,7 +1909,6 @@ function drawGlobe(ts) {
gctx.restore();
}
-requestAnimationFrame(drawGlobe);
const discoDots = document.getElementById('discoDots');
const strobeEl = document.getElementById('strobe');
@@ -1959,22 +1967,6 @@ setInterval(() => {
if (baladaAmt > 0.3 && discoDots.childElementCount < 28) spawnDiscoDot();
}, 280);
-/* ── Strobe no beat ── */
-let strobeCooldown = false;
-function triggerStrobe() {
- if (!balada || strobeCooldown) return;
- strobeCooldown = true;
- strobeEl.style.transition = 'none';
- strobeEl.style.opacity = '0.2';
- setTimeout(() => {
- strobeEl.style.transition = 'opacity 0.3s ease';
- strobeEl.style.opacity = '0';
- setTimeout(() => { strobeCooldown = false; }, 600);
- }, 50);
-}
-/* strobe desativado — muito agressivo visualmente */
-/* setInterval(() => { if (balada && Math.random() < 0.35) triggerStrobe(); }, BEAT_MS * 2); */
-
/* ── Pulso do sol/disco no beat ── */
function globeBeat() {
if (!balada || !sunEl) return;
@@ -1989,7 +1981,7 @@ setInterval(() => { if (balada) globeBeat(); }, BEAT_MS);
function setBaladaMode(on) {
if (on === balada) return;
balada = on;
- if (on) setChuvaMode(false);
+ if (on) { setChuvaMode(false); startGlobeLoop(); }
document.body.classList.toggle('balada', balada);
/* opacidade do globo é controlada por drawGlobe via baladaAmt */
}
@@ -2066,16 +2058,26 @@ function initRain() {
}
}
-let lastRainTs = 0;
+let lastRainTs = 0;
+let rainLoopOn = false;
+
+/* Loop roda só enquanto há chuva visível — dorme quando chuvaAmt zera */
+function startRainLoop() {
+ if (rainLoopOn) return;
+ rainLoopOn = true;
+ lastRainTs = 0;
+ requestAnimationFrame(drawRain);
+}
function drawRain(ts) {
- requestAnimationFrame(drawRain);
const dt = lastRainTs ? Math.min((ts - lastRainTs) / 1000, 0.05) : 0;
lastRainTs = ts;
chuvaAmt += ((chuva ? 1 : 0) - chuvaAmt) * Math.min(1, dt * 0.5);
const W = rainCanvas.width, H = rainCanvas.height;
rctx.clearRect(0, 0, W, H);
+ if (!chuva && chuvaAmt < 0.005) { rainLoopOn = false; return; }
+ requestAnimationFrame(drawRain);
if (chuvaAmt < 0.005) return;
rainDrops.forEach(d => {
@@ -2112,6 +2114,8 @@ function triggerLightning() {
}, delay);
delay += 100 + (Math.random() * 110 | 0);
}
+ /* limpa o tom azulado do strobe depois da rajada */
+ setTimeout(() => { strobeEl.style.background = ''; }, delay + 300);
}
(function scheduleLightning() {
@@ -2123,7 +2127,7 @@ function triggerLightning() {
function setChuvaMode(on) {
if (on === chuva) return;
chuva = on;
- if (on) setBaladaMode(false);
+ if (on) { setBaladaMode(false); startRainLoop(); }
document.body.classList.toggle('chuva', chuva);
if (on) {
fogWisps.forEach(w => {
@@ -2156,7 +2160,7 @@ let chuvaFileVal = null;
if (window.innerWidth > 0 && window.innerHeight > 0) {
resizeRain();
initRain();
- requestAnimationFrame(drawRain);
+ if (chuva) startRainLoop();
} else {
setTimeout(initRainOnLoad, 80);
}