import Plyr from 'plyr'; import CircleType from 'circletype'; // ---------------------------------------------------------------------------- // 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();