Files
chaospott-site/js/elevator.js
T
2026-06-02 02:36:05 +02:00

257 lines
6.2 KiB
JavaScript

/*!
* Elevator.js
*
* MIT licensed
* Copyright (C) 2015 Tim Holman, http://tholman.com
*/
/*********************************************
* Elevator.js
*********************************************/
var Elevator = function (options) {
'use strict';
// Elements
var body = null;
// Scroll vars
var animation = null;
var duration = null; // ms
var customDuration = false;
var startTime = null;
var startPosition = null;
var endPosition = 0;
var elevating = false;
var mainAudio;
var endAudio;
var mainAudioPath;
var endAudioPath;
var preloadAudio;
var loopAudio;
var that = this;
/**
* Utils
*/
// Thanks Mr Penner - http://robertpenner.com/easing/
function easeInOutQuad(t, b, c, d) {
t /= d / 2;
if (t < 1) return c / 2 * t * t + b;
t--;
return -c / 2 * (t * (t - 2) - 1) + b;
}
function extendParameters(options, defaults) {
for (var option in defaults) {
var t = options[option] === undefined && typeof option !== "function";
if (t) {
options[option] = defaults[option];
}
}
return options;
}
function getVerticalOffset(element) {
var verticalOffset = 0;
while (element) {
verticalOffset += element.offsetTop || 0;
element = element.offsetParent;
}
return verticalOffset;
}
function getScrollTop() {
return window.pageYOffset || document.documentElement.scrollTop || body.scrollTop || 0;
}
function playAudio(audio) {
var playPromise = audio.play();
if (playPromise && playPromise.catch) {
playPromise.catch(() => 0);
}
}
/**
* Main
*/
// Time is passed through requestAnimationFrame, what a world!
function animateLoop(time) {
if (!startTime) {
startTime = time;
}
var timeSoFar = time - startTime;
var easedPosition = easeInOutQuad(timeSoFar, startPosition, endPosition - startPosition, duration);
window.scrollTo(0, easedPosition);
if (timeSoFar < duration) {
animation = requestAnimationFrame(animateLoop);
} else {
animationFinished();
}
}
// ELEVATE!
// /
// ____
// .' '=====<0
// |======|
// |======|
// [IIIIII[\--()
// |_______|
// C O O O D
// C O O O D
// C O O O D
// C__O__O__O__D
// [_____________]
this.elevate = function () {
if (elevating) {
return;
}
elevating = true;
startPosition = getScrollTop();
// No custom duration set, so we travel at pixels per millisecond. (0.75px per ms)
if (!customDuration) {
duration = (startPosition * 1.5);
}
requestAnimationFrame(animateLoop);
loadAudio();
// Start music!
if (mainAudio) {
playAudio(mainAudio);
}
};
function browserMeetsRequirements() {
return window.requestAnimationFrame && window.Audio && window.addEventListener;
}
function resetPositions() {
startTime = null;
startPosition = null;
elevating = false;
}
function animationFinished() {
resetPositions();
// Stop music!
if (mainAudio) {
mainAudio.pause();
mainAudio.currentTime = 0;
}
if (endAudio) {
playAudio(endAudio);
}
}
function onWindowBlur() {
// If animating, go straight to the top. And play no more music.
if (elevating) {
cancelAnimationFrame(animation);
resetPositions();
if (mainAudio) {
mainAudio.pause();
mainAudio.currentTime = 0;
}
window.scrollTo(0, endPosition);
}
}
function handleElevate(event) {
if (event && event.type === 'touchend')
event.preventDefault();
that.elevate();
}
function bindElevateToElement(element) {
if (element.addEventListener) {
element.addEventListener('click', handleElevate, false);
element.addEventListener('touchend', handleElevate, false);
} else {
// Older browsers
element.attachEvent('onclick', function () {
document.documentElement.scrollTop = endPosition;
document.body.scrollTop = endPosition;
window.scroll(0, endPosition);
});
}
}
function loadAudio() {
if (!mainAudio && mainAudioPath) {
mainAudio = new Audio(mainAudioPath);
mainAudio.setAttribute('preload', preloadAudio);
mainAudio.setAttribute('loop', loopAudio);
}
if (!endAudio && endAudioPath) {
endAudio = new Audio(endAudioPath);
endAudio.setAttribute('preload', 'auto');
}
}
function init(_options) {
// Bind to element click event, if need be.
body = document.body;
var defaults = {
duration: undefined,
mainAudio: false,
endAudio: false,
preloadAudio: 'none',
loopAudio: true,
};
_options = extendParameters(_options, defaults);
if (_options.elements) {
for (var i = 0; i < _options.elements.length; i++) {
bindElevateToElement(_options.elements[i]);
}
} else if (_options.element) {
bindElevateToElement(_options.element);
}
// Take the stairs instead
if (!browserMeetsRequirements()) {
return;
}
if (_options.duration) {
customDuration = true;
duration = _options.duration;
}
if (_options.targetElement) {
endPosition = getVerticalOffset(_options.targetElement);
}
window.addEventListener('blur', onWindowBlur, false);
mainAudioPath = _options.mainAudio;
endAudioPath = _options.endAudio;
preloadAudio = _options.preloadAudio;
loopAudio = _options.loopAudio;
}
init(options);
};