feat: rewrite banner javascript system to accept custom banner data from PHP template

This commit is contained in:
David Bailey 2024-01-08 16:42:29 +01:00
parent 30019b4c47
commit 1b8bff401b
2 changed files with 150 additions and 55 deletions

View file

@ -1,69 +1,160 @@
const banner_show_time = 600 * 1000.0
const banner_animated_style = "opacity 0.8s linear, transform 0.1s linear"
const BANNER_TIME = 600 * 1000.0
const BANNER_ANIMATION = "opacity 0.8s linear, transform 0.1s linear"
var banner_current_src = localStorage.getItem('main_banner_img')
class BannerHandler {
constructor(banner_container, banner_image, banner_link) {
this.bannerContainerDOM = banner_container
this.bannerDOM = banner_image
this.bannerLinkDOM = banner_link
function getBannerTime() {
return (new Date()).getTime() / banner_show_time
}
function getBannerSrc() {
return "/static/banner/" + Math.floor(getBannerTime() + 1000/banner_show_time) % 2 + ".png"
}
function update_banner_top(banner, banner_container) {
const banner_top_max = 0
const banner_top_min = -banner.clientHeight + banner_container.clientHeight
this.bannerUpdateTimer = null
this.currentPhase = 0
const banner_top = (1-(getBannerTime()%1)) * banner_top_min
banner.style.transform = "translateY(" + banner_top + 'px' + ")"
}
this.currentBannerData = null
try {
this.currentBannerData = JSON.parse(localStorage.getItem('main_banner_img'))
} catch(e) {}
let banner_update_src = banner_current_src
function update_banner(banner, banner_container) {
this.currentBannerData ||= {}
image_select = getBannerSrc()
this.bannerDOM.onload=() => { this.onBannerLoaded() }
this.bannerDOM.onerror=() => {
this.fadeOut();
setTimeout(() => this.loadNextBanner(), 1000);
}
}
update_banner_top(banner, banner_container)
startUpdateTick() {
if(this.bannerUpdateTimer !== null) {
return
}
if(image_select != banner_update_src) {
banner.style.opacity = 0
console.log("Starting tick")
this.bannerUpdateTimer = setInterval(() => { this.updateTick() }, 100);
}
stopUpdateTick() {
if(this.bannerUpdateTimer === null) {
return
}
console.log("Stopping tick!")
clearInterval(this.bannerUpdateTimer);
this.bannerUpdateTimer = null
}
getPhase() {
return (new Date()).getTime() / BANNER_TIME;
}
getTargetBanner() {
if(window.dergBannerOptions == null) {
return {}
}
var banner_index = Math.floor(this.getPhase()) % window.dergBannerOptions.length
var banner_choice = window.dergBannerOptions[banner_index]
return banner_choice
}
updateTranslation() {
const bannerTranslateMax = -this.bannerDOM.clientHeight + this.bannerContainerDOM.clientHeight
const bannerPercentageFrom = this.currentBannerData.from || 0;
const bannerPercentageTo = this.currentBannerData.to || 1;
const bannerPercentage = (bannerPercentageFrom + (bannerPercentageTo - bannerPercentageFrom) * this.currentPhase)
const banner_top = (1-bannerPercentage) * bannerTranslateMax
this.bannerDOM.style.transform = "translateY(" + banner_top + 'px' + ")"
}
fadeOut() {
this.bannerDOM.style.opacity = 0;
}
fadeIn() {
this.bannerDOM.style.opacity = 0.3;
}
loadNextBanner() {
this.currentBannerData = this.getTargetBanner()
this.currentBannerData.bannerTime = new Date()
this.loadBanner()
}
loadBanner() {
console.log("Target banner:");
console.log(this.currentBannerData);
localStorage.setItem("main_banner_img", JSON.stringify(this.currentBannerData))
this.currentPhase = 0
if((this.currentBannerData === null)
|| (this.currentBannerData.src === undefined)) {
this.onBannerLoaded()
return
}
this.bannerDOM.src = this.currentBannerData.src
this.bannerLinkDOM.href = this.currentBannerData.href || this.currentBannerData.src
}
onBannerLoaded() {
console.log("Loaded?");
this.currentPhase = this.getPhase() % 1
this.updateTranslation()
this.fadeIn()
setTimeout(() => {
banner.src = image_select
}, 1000)
this.animateOn()
banner_update_src = image_select
localStorage.setItem('main_banner_img', image_select)
this.startUpdateTick()
}, 10)
}
document.getElementById("main_banner_img_link").href = "/gallery/test"
updateTick() {
console.log("tick")
const nextPhase = this.getPhase() % 1;
if((nextPhase > this.currentPhase)
&& (this.currentBannerData.src == this.getTargetBanner().src)) {
this.currentPhase = nextPhase;
this.updateTranslation();
} else {
this.fadeOut()
setTimeout(() => {
this.loadNextBanner()
}, 1000);
this.stopUpdateTick()
}
}
animateOn() {
this.bannerDOM.style.transition = BANNER_ANIMATION
}
start() {
this.fadeIn()
this.loadBanner()
}
}
const banner_container = document.getElementById("main_header")
const banner = document.getElementById("main_banner_img")
banner.addEventListener('load', () => {
update_banner_top(banner, banner_container)
const next_banner_src = getBannerSrc()
if(banner_current_src != next_banner_src) {
banner.style.transition = banner_animated_style
setTimeout(() => banner.style.opacity = 0.3, 1000)
}
else {
banner.style.opacity = 0.3
setTimeout(() => banner.style.transition = banner_animated_style, 0)
}
banner_current_src = next_banner_src
})
var bannerHandler = new BannerHandler(
document.getElementById("main_header"),
document.getElementById("main_banner_img"),
document.getElementById("main_banner_img_link"))
document.addEventListener("DOMContentLoaded", function () {
banner.src = getBannerSrc()
document.getElementById("main_banner_img_link").href = "/gallery/test"
})
bannerHandler.start()
setInterval(() => update_banner(banner, banner_container), 100)
addEventListener("resize", () => update_banner(banner, banner_container));
// addEventListener("resize", () => update_banner(banner, banner_container));

View file

@ -14,14 +14,18 @@
{% block extra_head %}{% endblock %}
{% block opengraph_tags %}{% endblock %}
<script src="/static/banner.js" defer></script>
</head>
<script type="text/javascript">
window.dergBannerOptions = JSON.parse('{{bannerJson|raw}}');
</script>
</head>
<body>
<header id="main_header">
<img id="main_banner_img"></img>
<a id="main_banner_img_link" href="/gallery"> full picture</a>
<script src="/static/banner.js"></script>
<h1 id="big_title">{% block big_title %}The dergsite{%endblock%}</h1>
{% block second_title %}{% endblock %}
<div id="title_separator"></div>