368 lines
12 KiB
JavaScript
368 lines
12 KiB
JavaScript
'use strict';
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// DATA
|
|
// ----------------------------------------------------------------------------
|
|
|
|
const root = document.documentElement;
|
|
|
|
// HOME NAVIGATION DISPLAY //
|
|
|
|
const navEl = document.querySelector('.home__nav');
|
|
const navLinks = document.querySelectorAll('.home__nav-link');
|
|
const navImage = document.querySelector('.home__nav-image');
|
|
const circleTypes = [];
|
|
|
|
// VIDEO PLAYERS //
|
|
|
|
const galleryVideos = document.querySelectorAll('.gallery__video');
|
|
let videoPlayers = [];
|
|
|
|
// HEADER BAR ANIMATION //
|
|
|
|
const headerBar = document.querySelector('.header-bar');
|
|
const headerLogo = document.querySelector('.header-bar__logo');
|
|
let scrollOffset = 0;
|
|
|
|
// NAVIGATION MENU ANIMATION //
|
|
|
|
const headerNavBtn = document.querySelector('.header-bar__nav-button');
|
|
const headerNavMenu = document.querySelector('.header-bar__nav-menu');
|
|
const headerNavMenuListEls = document.querySelectorAll('.header-bar__nav-menu li');
|
|
const headerNavOverlay = document.querySelector('.header-bar__nav-overlay');
|
|
const touchPosition = {
|
|
initialX: null,
|
|
initialY: null
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// UTILS
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Convert rem to pixels by getting font-size CSS property
|
|
function convertRemToPixels(rem) {
|
|
let fontSize = parseFloat(window.getComputedStyle(document.body).getPropertyValue('font-size'));
|
|
return rem * fontSize;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// LOGIC
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// HOME NAVIGATION DISPLAY //
|
|
|
|
// Calculate navigation grid inner width
|
|
function calculateNavGridInnerWidth() {
|
|
if (root && navImage) {
|
|
let navGridGapProperty = window.getComputedStyle(root).getPropertyValue('--home-nav-gap');
|
|
let navGridGap = parseFloat(navGridGapProperty.slice(0, -3));
|
|
return navImage.getBoundingClientRect().width + (convertRemToPixels(navGridGap) * 2);
|
|
}
|
|
}
|
|
|
|
// Calculate navigation grid inner diagonal
|
|
function calculateNavGridInnerDiagonal() {
|
|
return calculateNavGridInnerWidth() * Math.sqrt(2);
|
|
}
|
|
|
|
// Create new instance of CircleType for each navigation link, set radius and direction
|
|
function curveNavLinks() {
|
|
if (navLinks.length !== 0 && circleTypes) {
|
|
for (let i = 0; i < (navLinks.length - 2); i++) {
|
|
circleTypes[i] = new CircleType(navLinks[i]);
|
|
circleTypes[i].radius(calculateNavGridInnerWidth() / 2);
|
|
}
|
|
for (let i = (navLinks.length - 2); i < navLinks.length; i++) {
|
|
circleTypes[i] = new CircleType(navLinks[i]);
|
|
circleTypes[i].dir(-1);
|
|
circleTypes[i].radius(calculateNavGridInnerWidth() / 2);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set --home-nav-item-translation CSS property
|
|
function setNavItemTranslationProperty() {
|
|
let navItemTranslation = (calculateNavGridInnerDiagonal() - calculateNavGridInnerWidth()) / 2;
|
|
if (root) {
|
|
root.style.setProperty('--home-nav-item-translation', navItemTranslation + 'px');
|
|
}
|
|
}
|
|
|
|
// Set navigation grid display depending on number of links
|
|
function setNavGridDisplay() {
|
|
if (navEl && navLinks.length !== 0) {
|
|
if (navLinks.length === 2) {
|
|
navEl.classList.add('home__nav--2-items');
|
|
} else if (navLinks.length === 3) {
|
|
navEl.classList.add('home__nav--3-items');
|
|
} else if (navLinks.length === 4) {
|
|
navEl.classList.add('home__nav--4-items');
|
|
}
|
|
for (let i = 0; i < navLinks.length; i++) {
|
|
navLinks[i].classList.add('home__nav-link--visible');
|
|
}
|
|
}
|
|
}
|
|
|
|
// Edit navigation links radius and translation on window resize event
|
|
function editNavLinksOnResize() {
|
|
window.addEventListener('resize', function(e) {
|
|
if (navLinks.length !== 0 && circleTypes) {
|
|
for (let i = 0; i < navLinks.length; i++) {
|
|
circleTypes[i].radius(calculateNavGridInnerWidth() / 2);
|
|
}
|
|
}
|
|
setNavItemTranslationProperty();
|
|
});
|
|
}
|
|
|
|
// Add wave up animation to a single letter and remove it on animationend event
|
|
function waveNavLetterUp(navLetter) {
|
|
navLetter.classList.add('home__nav-letter--wave-up');
|
|
navLetter.addEventListener('animationend', function(e) {
|
|
navLetter.classList.remove('home__nav-letter--wave-up');
|
|
});
|
|
}
|
|
|
|
// Add wave down animation to a single letter and remove it on animationend event
|
|
function waveNavLetterDown(navLetter) {
|
|
navLetter.classList.add('home__nav-letter--wave-down');
|
|
navLetter.addEventListener('animationend', function(e) {
|
|
navLetter.classList.remove('home__nav-letter--wave-down');
|
|
});
|
|
}
|
|
|
|
// Add wave up animation to every letters of a single link with a slight delay
|
|
function waveNavLinkUp(navLink) {
|
|
let navLinkLetters = navLink.querySelectorAll('span');
|
|
let animationDelay = 0;
|
|
for (let i = 0; i < navLinkLetters.length; i++) {
|
|
setTimeout(waveNavLetterUp, animationDelay, navLinkLetters[i]);
|
|
animationDelay += 50;
|
|
}
|
|
}
|
|
|
|
// Add wave down animation to every letters of a single link with a slight delay
|
|
function waveNavLinkDown(navLink) {
|
|
let navLinkLetters = navLink.querySelectorAll('span');
|
|
let animationDelay = 0;
|
|
for (let i = 0; i < navLinkLetters.length; i++) {
|
|
setTimeout(waveNavLetterDown, animationDelay, navLinkLetters[i]);
|
|
animationDelay += 50;
|
|
}
|
|
}
|
|
|
|
// Add wave (up or down) animation to every letters of each link on mouseover event
|
|
function waveNavLinksOnHover() {
|
|
if (navLinks.length !== 0) {
|
|
for (let i = 0; i < (navLinks.length - 2); i++) {
|
|
navLinks[i].addEventListener('mouseover', function(e) {
|
|
waveNavLinkUp(navLinks[i]);
|
|
});
|
|
}
|
|
for (let i = (navLinks.length - 2); i < navLinks.length; i++) {
|
|
navLinks[i].addEventListener('mouseover', function(e) {
|
|
waveNavLinkDown(navLinks[i]);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// VIDEO PLAYERS //
|
|
|
|
// Set up Plyr video players
|
|
function setUpVideoPlayers() {
|
|
if (galleryVideos.length !== 0) {
|
|
videoPlayers = Plyr.setup(galleryVideos, {
|
|
controls: [
|
|
'play-large',
|
|
'play',
|
|
'progress',
|
|
'current-time',
|
|
'duration',
|
|
'mute',
|
|
'volume',
|
|
'fullscreen'
|
|
],
|
|
i18n: {
|
|
play: 'Lire',
|
|
pause: 'Mettre sur pause',
|
|
seek: 'Parcourir la piste audio',
|
|
currentTime: 'Temps écoulé depuis le début de la piste audio',
|
|
duration: 'Durée de la piste audio',
|
|
volume: 'Ajuster le volume',
|
|
mute: 'Couper le son',
|
|
unmute: 'Activer le son',
|
|
enterFullscreen: 'Activer le mode plein écran',
|
|
exitFullscreen: 'Quitter le mode plein écran'
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Toggle videos full screen mode on Plyr enterfullscreen and exitfullscreen media events
|
|
function toggleVideosFullScreen() {
|
|
if (videoPlayers.length !== 0) {
|
|
for (let i = 0; i < videoPlayers.length; i++) {
|
|
videoPlayers[i].on('enterfullscreen', function(e) {
|
|
galleryVideos[i].classList.add('gallery__video--full-screen');
|
|
});
|
|
videoPlayers[i].on('exitfullscreen', function(e) {
|
|
galleryVideos[i].classList.remove('gallery__video--full-screen');
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// HEADER BAR ANIMATION //
|
|
|
|
// Toggle header bar depending on scroll offset
|
|
function toggleHeaderBar() {
|
|
if (headerBar && headerLogo) {
|
|
let headerBarHeight = headerBar.getBoundingClientRect().height;
|
|
if (window.pageYOffset > headerBarHeight) { // Scroll down past header bar height
|
|
headerBar.classList.add('header-bar--fixed');
|
|
headerLogo.classList.add('header-bar__logo--small');
|
|
} else if (window.pageYOffset <= 0) {
|
|
headerBar.classList.remove('header-bar--fixed');
|
|
headerLogo.classList.remove('header-bar__logo--small');
|
|
headerBar.classList.remove('header-bar--visible');
|
|
}
|
|
if (headerBar.classList.contains('header-bar--fixed')) {
|
|
if (scrollOffset < window.pageYOffset) { // Scroll down
|
|
headerBar.classList.remove('header-bar--visible');
|
|
} else if (scrollOffset > window.pageYOffset) { // Scroll up
|
|
headerBar.classList.add('header-bar--visible');
|
|
}
|
|
scrollOffset = window.pageYOffset;
|
|
}
|
|
}
|
|
}
|
|
|
|
// NAVIGATION MENU ANIMATION //
|
|
|
|
// Toggle header navigation
|
|
function toggleHeaderNav() {
|
|
if (headerNavBtn && headerNavMenu) {
|
|
headerNavBtn.classList.toggle('header-bar__nav-button--custom-focus');
|
|
headerNavMenu.classList.toggle('header-bar__nav-menu--visible');
|
|
headerNavOverlay.classList.toggle('header-bar__nav-overlay--visible');
|
|
document.body.classList.toggle('body--hidden-overflow-y');
|
|
}
|
|
}
|
|
|
|
// Open header navigation
|
|
function openHeaderNav() {
|
|
if (headerNavBtn && headerNavMenu) {
|
|
headerNavBtn.classList.add('header-bar__nav-button--custom-focus');
|
|
headerNavMenu.classList.add('header-bar__nav-menu--visible');
|
|
headerNavOverlay.classList.add('header-bar__nav-overlay--visible');
|
|
document.body.classList.add('body--hidden-overflow-y');
|
|
}
|
|
}
|
|
|
|
// Close header navigation
|
|
function closeHeaderNav() {
|
|
if (headerNavBtn && headerNavMenu) {
|
|
headerNavBtn.classList.remove('header-bar__nav-button--custom-focus');
|
|
headerNavMenu.classList.remove('header-bar__nav-menu--visible');
|
|
headerNavOverlay.classList.remove('header-bar__nav-overlay--visible');
|
|
document.body.classList.remove('body--hidden-overflow-y');
|
|
}
|
|
}
|
|
|
|
// Toggle header navigation on button click event
|
|
function toggleHeaderNavOnClick() {
|
|
headerNavBtn.addEventListener('click', toggleHeaderNav);
|
|
}
|
|
|
|
// Close header navigation on document click event
|
|
function closeHeaderNavOnClick() {
|
|
document.addEventListener('click', function(e) {
|
|
if (headerNavBtn.classList.contains('header-bar__nav-button--custom-focus') && headerNavMenu.classList.contains('header-bar__nav-menu--visible') && !headerNavBtn.contains(e.target) && !headerNavMenu.contains(e.target)) {
|
|
closeHeaderNav(e);
|
|
if (e.cancelable) {
|
|
e.preventDefault();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Open header navigation on menu list focusin event
|
|
function openHeaderNavBeforeFocus() {
|
|
if (headerNavMenuListEls) {
|
|
for (let i = 0; i < headerNavMenuListEls.length; i++) {
|
|
headerNavMenuListEls[i].addEventListener('focusin', openHeaderNav);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Close header navigation on menu list focusout event
|
|
function closeHeaderNavAfterFocus() {
|
|
if (headerNavMenuListEls) {
|
|
for (let i = 0; i < headerNavMenuListEls.length; i++) {
|
|
headerNavMenuListEls[i].addEventListener('focusout', closeHeaderNav);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Close header navigation on touchstart and touchmove events (swipe right)
|
|
function closeHeaderNavOnSwipe() {
|
|
headerNavMenu.addEventListener('touchstart', function(e) {
|
|
if (headerNavBtn.classList.contains('header-bar__nav-button--custom-focus') && headerNavMenu.classList.contains('header-bar__nav-menu--visible') && touchPosition.initialX === null && touchPosition.initialY === null) {
|
|
touchPosition.initialX = event.touches[0].clientX;
|
|
touchPosition.initialY = event.touches[0].clientY;
|
|
}
|
|
}, {passive: true});
|
|
headerNavMenu.addEventListener('touchmove', function(e) {
|
|
if (headerNavBtn.classList.contains('header-bar__nav-button--custom-focus') && headerNavMenu.classList.contains('header-bar__nav-menu--visible') && touchPosition.initialX !== null && touchPosition.initialY !== null) {
|
|
touchPosition.currentX = event.touches[0].clientX;
|
|
touchPosition.currentY = event.touches[0].clientY;
|
|
touchPosition.diffX = touchPosition.initialX - touchPosition.currentX;
|
|
touchPosition.diffY = touchPosition.initialY - touchPosition.currentY;
|
|
if (Math.abs(touchPosition.diffX) > Math.abs(touchPosition.diffY)) {
|
|
if (touchPosition.diffX < 0) {
|
|
closeHeaderNav(e);
|
|
}
|
|
}
|
|
touchPosition.initialX = null;
|
|
touchPosition.initialY = null;
|
|
}
|
|
}, {passive: true});
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// PROGRAM
|
|
// ----------------------------------------------------------------------------
|
|
|
|
// Enable CSS :active pseudo-class in Safari Mobile
|
|
document.addEventListener("touchstart", function() {},false);
|
|
|
|
// HOME NAVIGATION DISPLAY //
|
|
|
|
window.addEventListener('load', function() {
|
|
curveNavLinks();
|
|
setNavItemTranslationProperty();
|
|
setNavGridDisplay();
|
|
editNavLinksOnResize();
|
|
waveNavLinksOnHover();
|
|
});
|
|
|
|
// VIDEO PLAYERS //
|
|
|
|
setUpVideoPlayers();
|
|
toggleVideosFullScreen();
|
|
|
|
// HEADER BAR ANIMATION //
|
|
|
|
document.addEventListener('scroll', function() {
|
|
toggleHeaderBar();
|
|
});
|
|
|
|
// NAVIGATION MENU ANIMATION //
|
|
|
|
toggleHeaderNavOnClick();
|
|
closeHeaderNavOnClick();
|
|
openHeaderNavBeforeFocus();
|
|
closeHeaderNavAfterFocus();
|
|
closeHeaderNavOnSwipe();
|