Refactor bunny visibility toggle logic; streamline code and improve readability
This commit is contained in:
@@ -53,7 +53,6 @@
|
||||
left: 0;
|
||||
width: 160px;
|
||||
height: auto;
|
||||
z-index: 1002;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ const config = window.SeasonalsPluginConfig?.Easter || {};
|
||||
|
||||
const easter = config.EnableEaster !== undefined ? config.EnableEaster : true;
|
||||
const enableBunny = config.EnableBunny !== undefined ? config.EnableBunny : true;
|
||||
/* MARK: BUNNY LOCOMOTION CONFIGURATION */
|
||||
/* MARK: Bunny movement config */
|
||||
const jumpDistanceVw = 5; // Distance in vw the bunny covers per jump
|
||||
const jumpDurationMs = 770; // Time in ms the bunny spends moving during a jump
|
||||
const pauseDurationMs = 116.6666; // Time in ms the bunny pauses between jumps
|
||||
@@ -29,6 +29,39 @@ const easterEggImages = [
|
||||
"../Seasonals/Resources/easter_images/eggs.png"
|
||||
];
|
||||
|
||||
|
||||
// Check visibility
|
||||
function toggleEaster() {
|
||||
const easterContainer = document.querySelector('.easter-container');
|
||||
if (!easterContainer) return;
|
||||
|
||||
const videoPlayer = document.querySelector('.videoPlayerContainer');
|
||||
const trailerPlayer = document.querySelector('.youtubePlayerContainer');
|
||||
const isDashboard = document.body.classList.contains('dashboardDocument');
|
||||
const hasUserMenu = document.querySelector('#app-user-menu');
|
||||
|
||||
if (videoPlayer || trailerPlayer || isDashboard || hasUserMenu) {
|
||||
easterContainer.style.display = 'none';
|
||||
if (rabbitTimeout) {
|
||||
clearTimeout(rabbitTimeout);
|
||||
isAnimating = false; // Reset to allow restarting later
|
||||
}
|
||||
} else {
|
||||
easterContainer.style.display = 'block';
|
||||
if (!isAnimating && enableBunny) {
|
||||
animateRabbit(document.querySelector('#rabbit'));
|
||||
}
|
||||
}
|
||||
}
|
||||
const observer = new MutationObserver(toggleEaster);
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true,
|
||||
attributes: true
|
||||
});
|
||||
|
||||
|
||||
function createEasterGrassAndEggs(container) {
|
||||
let grassContainer = container.querySelector('.easter-grass-container');
|
||||
if (!grassContainer) {
|
||||
@@ -164,16 +197,12 @@ function animateRabbit(rabbit) {
|
||||
function animationStep(timestamp) {
|
||||
if (!document.querySelector('.easter-container') || rabbit.style.display === 'none') {
|
||||
isAnimating = false;
|
||||
// When hidden, we stop animating. The toggle function will re-init.
|
||||
return;
|
||||
}
|
||||
|
||||
if (!startTime) {
|
||||
startTime = timestamp;
|
||||
// FORCE GIF RESTART:
|
||||
// The GIF must restart exactly when the jump loop starts.
|
||||
// Re-assigning the src without a cache-busting timestamp resets it to frame 0
|
||||
// while still allowing the browser to serve the cached file immediately.
|
||||
// resetting gif, forces the browser to restart the GIF from the first frame (crucial for syncing hops with movement)
|
||||
const currSrc = rabbit.src.split('?')[0];
|
||||
rabbit.src = '';
|
||||
rabbit.src = currSrc;
|
||||
@@ -181,7 +210,6 @@ function animateRabbit(rabbit) {
|
||||
|
||||
const elapsed = timestamp - startTime;
|
||||
|
||||
// Calculate how many full loops (jump+pause) have happened
|
||||
const completedLoops = Math.floor(elapsed / loopDurationMs);
|
||||
const timeInCurrentLoop = elapsed % loopDurationMs;
|
||||
|
||||
@@ -197,14 +225,11 @@ function animateRabbit(rabbit) {
|
||||
|
||||
currentX = startX + (completedLoops * jumpDistanceVw + currentLoopDistance) * direction;
|
||||
|
||||
// Update DOM without CSS transitions (since we control it per-frame)
|
||||
// Update DOM without CSS transitions
|
||||
rabbit.style.transform = `translateX(${currentX}vw) ${transformScale}`;
|
||||
|
||||
// Check if finished crossing
|
||||
if ((direction === 1 && currentX >= endX) || (direction === -1 && currentX <= endX)) {
|
||||
// Finished crossing! We can rest now.
|
||||
// Since we explicitly reset the GIF to frame 0 at the start of every loop,
|
||||
// we no longer have to snap the rest time to the loop duration mathematically.
|
||||
let restTime = Math.random() * (maxBunnyRestTime - minBunnyRestTime) + minBunnyRestTime;
|
||||
|
||||
isAnimating = false;
|
||||
@@ -221,33 +246,6 @@ function animateRabbit(rabbit) {
|
||||
rabbitTimeout = requestAnimationFrame(animationStep);
|
||||
}
|
||||
|
||||
// Check visibility
|
||||
function toggleEaster() {
|
||||
const easterContainer = document.querySelector('.easter-container');
|
||||
if (!easterContainer) return;
|
||||
|
||||
const videoPlayer = document.querySelector('.videoPlayerContainer');
|
||||
const trailerPlayer = document.querySelector('.youtubePlayerContainer');
|
||||
const isDashboard = document.body.classList.contains('dashboardDocument');
|
||||
const hasUserMenu = document.querySelector('#app-user-menu');
|
||||
|
||||
if (videoPlayer || trailerPlayer || isDashboard || hasUserMenu) {
|
||||
easterContainer.style.display = 'none';
|
||||
if (rabbitTimeout) {
|
||||
clearTimeout(rabbitTimeout);
|
||||
isAnimating = false; // Reset to allow restarting later
|
||||
}
|
||||
} else {
|
||||
easterContainer.style.display = 'block';
|
||||
if (!isAnimating && enableBunny) {
|
||||
animateRabbit(document.querySelector('#rabbit'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const observer = new MutationObserver(toggleEaster);
|
||||
observer.observe(document.body, { childList: true, subtree: true, attributes: true });
|
||||
|
||||
function initializeEaster() {
|
||||
if (!easter) return;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user