Adding a halloween animation special for the client

canary
WolverinDEV 2020-10-04 20:47:19 +02:00
parent 63ee86a2de
commit 2a172565a8
9 changed files with 97 additions and 33 deletions

View File

@ -4,8 +4,9 @@ import {getUrlParameter} from "./loader/utils";
let overlay: HTMLDivElement; let overlay: HTMLDivElement;
let setupContainer: HTMLDivElement; let setupContainer: HTMLDivElement;
let idleContainer: HTMLDivElement; let idleNormalContainer: HTMLDivElement;
let idleSteamContainer: HTMLDivElement; let idleNormalSteamContainer: HTMLDivElement;
let idleHalloweenContainer: HTMLDivElement;
let loaderStageContainer: HTMLDivElement; let loaderStageContainer: HTMLDivElement;
let finalizing = false; let finalizing = false;
@ -14,6 +15,9 @@ let initializeTimestamp;
let verbose = false; let verbose = false;
let apngSupport = undefined; let apngSupport = undefined;
let loopInterval: number;
let animationType: "normal" | "halloween";
async function detectAPNGSupport() { async function detectAPNGSupport() {
const image = new Image(); const image = new Image();
const ctx = document.createElement("canvas").getContext("2d"); const ctx = document.createElement("canvas").getContext("2d");
@ -29,10 +33,16 @@ async function detectAPNGSupport() {
function initializeElements() { function initializeElements() {
overlay = document.getElementById("loader-overlay") as HTMLDivElement; overlay = document.getElementById("loader-overlay") as HTMLDivElement;
if(!overlay) if(!overlay) {
throw "missing loader overlay"; throw "missing loader overlay";
}
for(const lazyImage of [...overlay.getElementsByTagName("lazy-img")]) { for(const lazyImage of [...overlay.getElementsByTagName("lazy-img")]) {
if(lazyImage.hasAttribute("x-animation-depend") && lazyImage.getAttribute("x-animation-depend") !== animationType) {
lazyImage.remove();
continue;
}
const image = document.createElement("img"); const image = document.createElement("img");
image.alt = lazyImage.getAttribute("alt"); image.alt = lazyImage.getAttribute("alt");
image.src = lazyImage.getAttribute(apngSupport ? "src-apng" : "src-gif") || lazyImage.getAttribute("src"); image.src = lazyImage.getAttribute(apngSupport ? "src-apng" : "src-gif") || lazyImage.getAttribute("src");
@ -42,27 +52,51 @@ function initializeElements() {
} }
setupContainer = overlay.getElementsByClassName("setup")[0] as HTMLDivElement; setupContainer = overlay.getElementsByClassName("setup")[0] as HTMLDivElement;
if(!setupContainer) if(!setupContainer) {
throw "missing setup container"; throw "missing setup container";
}
idleContainer = overlay.getElementsByClassName("idle")[0] as HTMLDivElement; idleNormalContainer = overlay.getElementsByClassName("idle animation-normal")[0] as HTMLDivElement;
if(!idleContainer) if(!idleNormalContainer) {
throw "missing idle container"; throw "missing normal idle container";
}
idleSteamContainer = idleContainer.getElementsByClassName("steam")[0] as HTMLDivElement; idleHalloweenContainer = overlay.getElementsByClassName("idle animation-halloween")[0] as HTMLDivElement;
if(!idleSteamContainer) if(!idleHalloweenContainer) {
throw "missing idle steam container"; throw "missing halloween idle container";
}
idleNormalSteamContainer = idleNormalContainer.getElementsByClassName("steam")[0] as HTMLDivElement;
if(!idleNormalSteamContainer) {
throw "missing normal idle steam container";
}
loaderStageContainer = overlay.getElementsByClassName("loader-stage")[0] as HTMLDivElement; loaderStageContainer = overlay.getElementsByClassName("loader-stage")[0] as HTMLDivElement;
if(!loaderStageContainer) if(!loaderStageContainer) {
throw "missing loader stage container"; throw "missing loader stage container";
}
setupContainer.onanimationend = setupAnimationFinished; setupContainer.onanimationend = setupAnimationFinished;
idleSteamContainer.onanimationiteration = idleSteamAnimationLooped; idleHalloweenContainer.onanimationiteration = idleSteamAnimationLooped;
idleNormalSteamContainer.onanimationiteration = idleSteamAnimationLooped;
overlay.onanimationend = overlayAnimationFinished; overlay.onanimationend = overlayAnimationFinished;
} }
export async function initialize() { export async function initialize(customLoadingAnimations: boolean) {
if(customLoadingAnimations) {
const now = new Date();
/* Note, the months start with zero */
if(now.getMonth() === 9) {
animationType = "halloween";
} else if(now.getMonth() === 10 && now.getDay() <= 5) {
animationType = "halloween";
}
}
if(!animationType) {
animationType = "normal";
}
await detectAPNGSupport(); await detectAPNGSupport();
try { try {
initializeElements(); initializeElements();
@ -85,7 +119,7 @@ export async function initialize() {
if(parseInt(getUrlParameter("animation-short")) === 1) { if(parseInt(getUrlParameter("animation-short")) === 1) {
setupAnimationFinished(); setupAnimationFinished();
} else { } else {
setupContainer.classList.add("visible"); setupContainer.classList.add("visible", animationType);
} }
initializeTimestamp = Date.now(); initializeTimestamp = Date.now();
@ -94,6 +128,8 @@ export async function initialize() {
export function abort() { export function abort() {
overlay?.remove(); overlay?.remove();
clearInterval(loopInterval);
loopInterval = 0;
} }
export function finalize() { export function finalize() {
@ -102,8 +138,9 @@ export function finalize() {
} else { } else {
finalizing = true; finalizing = true;
if(loaderStageContainer) if(loaderStageContainer) {
loaderStageContainer.innerText = "app loaded successfully (" + (Date.now() - initializeTimestamp) + "ms)"; loaderStageContainer.innerText = "app loaded successfully (" + (Date.now() - initializeTimestamp) + "ms)";
}
} }
} }
@ -117,21 +154,30 @@ function setupAnimationFinished() {
verbose && console.log("Entering idle animation"); verbose && console.log("Entering idle animation");
setupContainer.classList.remove("visible"); setupContainer.classList.remove("visible");
idleContainer.classList.add("visible"); if(animationType === "halloween") {
loopInterval = setInterval(() => idleSteamAnimationLooped(), 1000);
idleHalloweenContainer.classList.add("visible");
} else {
idleNormalContainer.classList.add("visible");
}
} }
function idleSteamAnimationLooped() { function idleSteamAnimationLooped() {
verbose && console.log("Idle animation looped. Should finalize: %o", finalizing); verbose && console.log("Idle animation looped. Should finalize: %o", finalizing);
if(!finalizing) if(!finalizing) {
return; return;
}
clearInterval(loopInterval);
loopInterval = 0;
overlay.classList.add("finishing"); overlay.classList.add("finishing");
} }
function overlayAnimationFinished(event: AnimationEvent) { function overlayAnimationFinished(event: AnimationEvent) {
/* the text animation is the last one */ /* the text animation is the last one */
if(event.animationName !== "swipe-out-text") if(event.animationName !== "swipe-out-text") {
return; return;
}
verbose && console.log("Animation finished"); verbose && console.log("Animation finished");
overlay.remove(); overlay.remove();

View File

@ -187,8 +187,8 @@ export function setCurrentTaskName(taskId: number, name: string) {
Animation.updateState(currentStage, runningTasks.map(e => e.name)); Animation.updateState(currentStage, runningTasks.map(e => e.name));
} }
export async function execute() { export async function execute(customLoadingAnimations: boolean) {
if(!await Animation.initialize()) if(!await Animation.initialize(customLoadingAnimations))
return; return;
loader_cache_tag(); loader_cache_tag();
@ -301,8 +301,8 @@ export async function execute() {
Animation.finalize(); Animation.finalize();
} }
export function execute_managed() { export function execute_managed(customLoadingAnimations: boolean) {
execute().then(() => { execute(customLoadingAnimations).then(() => {
if(config.verbose) { if(config.verbose) {
let message; let message;
if(typeof(window.tr) !== "undefined") if(typeof(window.tr) !== "undefined")

View File

@ -149,6 +149,6 @@ loader.register_task(loader.Stage.SETUP, {
export default class implements ApplicationLoader { export default class implements ApplicationLoader {
execute() { execute() {
loader.execute_managed(); loader.execute_managed(true);
} }
} }

View File

@ -24,6 +24,6 @@ export default class implements ApplicationLoader {
} }
}); });
loader.execute_managed(); loader.execute_managed(false);
} }
} }

View File

@ -65,6 +65,6 @@ export default class implements ApplicationLoader {
priority: 10 priority: 10
}); });
loader.execute_managed(); loader.execute_managed(false);
} }
} }

View File

@ -1,4 +1,6 @@
$setup-time: 80s / 24; /* 24 frames / sec; the initial sequence is 80 seconds */ $setup-time-normal: 80s / 24; /* 24 frames / sec; the initial sequence is 80 frames */
$setup-time-halloween: 323s / 24;
$loop-time-halloween: 25s / 24;
#loader-overlay { #loader-overlay {
position: absolute; position: absolute;
@ -56,10 +58,16 @@ $setup-time: 80s / 24; /* 24 frames / sec; the initial sequence is 80 seconds */
} }
.setup.visible { .setup.visible {
animation: loader-initial-sequence 0s cubic-bezier(.81,.01,.65,1.16) $setup-time forwards; &.normal {
animation: loader-initial-sequence 0s cubic-bezier(.81,.01,.65,1.16) $setup-time-normal forwards;
}
&.halloween {
animation: loader-initial-sequence 0s cubic-bezier(.81,.01,.65,1.16) $setup-time-halloween forwards;
}
} }
.idle { .idle.animation-normal {
img { img {
position: absolute; position: absolute;
} }
@ -172,6 +180,12 @@ $setup-time: 80s / 24; /* 24 frames / sec; the initial sequence is 80 seconds */
} }
} }
@keyframes animation-nothing {
to {
background-position: 0 -6250px;
}
}
@keyframes overlay-fade { @keyframes overlay-fade {
to { to {
opacity: 0; opacity: 0;
@ -183,7 +197,7 @@ $setup-time: 80s / 24; /* 24 frames / sec; the initial sequence is 80 seconds */
display: block !important; display: block !important;
opacity: 0; opacity: 0;
animation: loader-setup-timeout 0s ease-in $setup-time forwards; animation: loader-setup-timeout 0s ease-in $setup-time-normal forwards;
.error::before { .error::before {
content: 'Failed to startup loader!'; content: 'Failed to startup loader!';

View File

@ -75,13 +75,17 @@ var initial_css;
<div class="loader" id="loader-overlay"> <div class="loader" id="loader-overlay">
<div class="container"> <div class="container">
<div class="setup"> <div class="setup">
<lazy-img src="img/loader/initial-sequence.gif" alt="initial loading sequence"></lazy-img> <lazy-img src="img/loader/initial-sequence.gif" alt="initial loading sequence" x-animation-depend="normal"></lazy-img>
<lazy-img src="img/loader/halloween-initial-sequence.gif" alt="initial loading sequence" x-animation-depend="halloween"></lazy-img>
</div> </div>
<div class="idle"> <div class="idle animation-normal">
<lazy-img class="bowl" src="img/loader/bowl.png" alt="bowl"></lazy-img> <lazy-img class="bowl" src="img/loader/bowl.png" alt="bowl" x-animation-depend="normal"></lazy-img>
<lazy-img class="text" src="img/loader/text.png" alt="TeaSpeak"></lazy-img> <lazy-img class="text" src="img/loader/text.png" alt="TeaSpeak" x-animation-depend="normal"></lazy-img>
<div class="steam"></div> <div class="steam"></div>
</div> </div>
<div class="idle animation-halloween">
<lazy-img src="img/loader/halloween-loop.gif" alt="halloween loop" x-animation-depend="halloween"></lazy-img>
</div>
</div> </div>
<div class="loader-stage"></div> <div class="loader-stage"></div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 472 KiB