diff --git a/assets/css/src/_index.scss b/assets/css/src/_index.scss index ed390d3..8c93d01 100644 --- a/assets/css/src/_index.scss +++ b/assets/css/src/_index.scss @@ -31,7 +31,7 @@ body[data-template="index"] { section.toggle { .project-slideshow { - picture:not(.active) { + .slide:not(.active) { display: none; } } diff --git a/assets/css/src/_main.scss b/assets/css/src/_main.scss index c0cfd06..9c76e40 100644 --- a/assets/css/src/_main.scss +++ b/assets/css/src/_main.scss @@ -121,7 +121,8 @@ button#mobile-menu-toggle { right: 0; position: absolute; - picture img { + picture img, + video.slide { max-width: 100%; max-height: calc(100vh - var(--body-margin) * 2); vertical-align: bottom; diff --git a/assets/css/src/_mobile.scss b/assets/css/src/_mobile.scss index 6d0e524..1b755b4 100644 --- a/assets/css/src/_mobile.scss +++ b/assets/css/src/_mobile.scss @@ -26,14 +26,16 @@ inset: 0; width: auto; height: auto; - picture { + picture, + video.slide { inset: 0; position: absolute; - img { - width: 100%; - height: 100%; - object-fit: cover; - } + } + picture img, + video.slide { + width: 100%; + height: 100%; + object-fit: cover; } } diff --git a/assets/css/style.css b/assets/css/style.css index 13ce88f..c53aa44 100644 --- a/assets/css/style.css +++ b/assets/css/style.css @@ -121,7 +121,8 @@ button#mobile-menu-toggle { right: 0; position: absolute; } -.project-slideshow picture img { +.project-slideshow picture img, +.project-slideshow video.slide { max-width: 100%; max-height: calc(100vh - var(--body-margin) * 2); vertical-align: bottom; @@ -586,7 +587,7 @@ body[data-template=index] .filter-menu ul { body[data-template=index] .projects-index li.filtered-out { display: none; } -body[data-template=index] .projects-index li section.toggle .project-slideshow picture:not(.active) { +body[data-template=index] .projects-index li section.toggle .project-slideshow .slide:not(.active) { display: none; } body[data-template=index] ul.projects-index { @@ -621,11 +622,13 @@ body[data-template=index] ul.projects-index { width: auto; height: auto; } - .project-slideshow picture { + .project-slideshow picture, + .project-slideshow video.slide { inset: 0; position: absolute; } - .project-slideshow picture img { + .project-slideshow picture img, + .project-slideshow video.slide { width: 100%; height: 100%; -o-object-fit: cover; diff --git a/assets/js/project-slideshow.js b/assets/js/project-slideshow.js index 0996b3b..7178bea 100644 --- a/assets/js/project-slideshow.js +++ b/assets/js/project-slideshow.js @@ -7,116 +7,104 @@ document.addEventListener("DOMContentLoaded", () => { const firstProject = projects[0]; const lastProject = projects[projects.length - 1]; - const firstPictureFirstProject = firstProject.querySelector( - ".project-slideshow picture:first-of-type", - ); - const firstPictureLastProject = lastProject.querySelector( - ".project-slideshow picture:first-of-type", - ); - const lastPictureLastProject = lastProject.querySelector( - ".project-slideshow picture:last-of-type", - ); + // Première / dernière slide d'un projet (image OU vidéo). + // On cible la classe « .slide » au lieu de la balise « picture » + // pour que les vidéos comptent comme des slides normales. + const firstSlide = (project) => + project.querySelector(".project-slideshow > .slide"); + const lastSlide = (project) => { + const slides = project.querySelectorAll(".project-slideshow > .slide"); + return slides[slides.length - 1]; + }; + + const firstSlideFirstProject = firstSlide(firstProject); + const firstSlideLastProject = firstSlide(lastProject); + const lastSlideLastProject = lastSlide(lastProject); // Fonctions de navigation : les éléments « courants » sont re-requêtés // à chaque appel pour refléter l'état actuel du DOM. function goToNextPicture() { - const activePicture = document.querySelector( - ".project.selected .project-slideshow > picture.active", - ); - const lastPicture = document.querySelector( - ".project.selected .project-slideshow > picture:last-of-type", - ); const selectedProject = document.querySelector(".project.selected"); - const nextProject = selectedProject.nextElementSibling; - const firstPictureNextProject = nextProject?.querySelector( - ".project-slideshow picture:first-of-type", + const activeSlide = selectedProject.querySelector( + ".project-slideshow > .slide.active", ); + const lastSlideSelected = lastSlide(selectedProject); + const nextProject = selectedProject.nextElementSibling; - if (activePicture !== lastPicture) { - activePicture.classList.remove("active"); - activePicture.nextElementSibling.classList.add("active"); + if (activeSlide !== lastSlideSelected) { + activeSlide.classList.remove("active"); + activeSlide.nextElementSibling.classList.add("active"); } else { selectedProject.classList.remove("selected"); - activePicture.classList.remove("active"); + activeSlide.classList.remove("active"); if (selectedProject !== lastProject) { nextProject.classList.add("selected"); - firstPictureNextProject.classList.add("active"); + firstSlide(nextProject).classList.add("active"); } else { firstProject.classList.add("selected"); - firstPictureFirstProject.classList.add("active"); + firstSlideFirstProject.classList.add("active"); } } } function goToPrevPicture() { - const activePicture = document.querySelector( - ".project.selected .project-slideshow > picture.active", - ); - const firstPicture = document.querySelector( - ".project.selected .project-slideshow > picture:first-of-type", - ); const selectedProject = document.querySelector(".project.selected"); - const prevProject = selectedProject.previousElementSibling; - const lastPicturePrevProject = prevProject?.querySelector( - ".project-slideshow picture:last-of-type", + const activeSlide = selectedProject.querySelector( + ".project-slideshow > .slide.active", ); + const firstSlideSelected = firstSlide(selectedProject); + const prevProject = selectedProject.previousElementSibling; - if (activePicture !== firstPicture) { - activePicture.classList.remove("active"); - activePicture.previousElementSibling.classList.add("active"); + if (activeSlide !== firstSlideSelected) { + activeSlide.classList.remove("active"); + activeSlide.previousElementSibling.classList.add("active"); } else { selectedProject.classList.remove("selected"); - activePicture.classList.remove("active"); + activeSlide.classList.remove("active"); if (selectedProject !== firstProject) { prevProject.classList.add("selected"); - lastPicturePrevProject.classList.add("active"); + lastSlide(prevProject).classList.add("active"); } else { lastProject.classList.add("selected"); - lastPictureLastProject.classList.add("active"); + lastSlideLastProject.classList.add("active"); } } } function goToPrevProject() { - const activePicture = document.querySelector( - ".project.selected .project-slideshow > picture.active", - ); const selectedProject = document.querySelector(".project.selected"); - const prevProject = selectedProject.previousElementSibling; - const firstPicturePrevProject = prevProject?.querySelector( - ".project-slideshow picture:first-of-type", + const activeSlide = selectedProject.querySelector( + ".project-slideshow > .slide.active", ); + const prevProject = selectedProject.previousElementSibling; - activePicture.classList.remove("active"); + activeSlide.classList.remove("active"); selectedProject.classList.remove("selected"); if (selectedProject !== firstProject) { prevProject.classList.add("selected"); - firstPicturePrevProject.classList.add("active"); + firstSlide(prevProject).classList.add("active"); } else { lastProject.classList.add("selected"); - firstPictureLastProject.classList.add("active"); + firstSlideLastProject.classList.add("active"); } } function goToNextProject() { - const activePicture = document.querySelector( - ".project.selected .project-slideshow > picture.active", - ); const selectedProject = document.querySelector(".project.selected"); - const nextProject = selectedProject.nextElementSibling; - const firstPictureNextProject = nextProject?.querySelector( - ".project-slideshow picture:first-of-type", + const activeSlide = selectedProject.querySelector( + ".project-slideshow > .slide.active", ); + const nextProject = selectedProject.nextElementSibling; - activePicture.classList.remove("active"); + activeSlide.classList.remove("active"); selectedProject.classList.remove("selected"); if (selectedProject !== lastProject) { nextProject.classList.add("selected"); - firstPictureNextProject.classList.add("active"); + firstSlide(nextProject).classList.add("active"); } else { firstProject.classList.add("selected"); - firstPictureFirstProject.classList.add("active"); + firstSlideFirstProject.classList.add("active"); } } diff --git a/assets/js/project-toggle.js b/assets/js/project-toggle.js index cf1669b..b1b849e 100644 --- a/assets/js/project-toggle.js +++ b/assets/js/project-toggle.js @@ -22,9 +22,11 @@ allProjects.forEach((currentProject) => { }); currentProject - .querySelectorAll("picture") - .forEach((picture) => picture.classList.remove("active")); - currentProject.querySelector("picture:first-child").classList.add("active"); + .querySelectorAll(".project-slideshow > .slide") + .forEach((slide) => slide.classList.remove("active")); + currentProject + .querySelector(".project-slideshow > .slide") + .classList.add("active"); currentProject.classList.toggle("selected"); Router.setParam("project", currentProject.dataset.slug); diff --git a/site/templates/index.php b/site/templates/index.php index d342b82..5a5c590 100644 --- a/site/templates/index.php +++ b/site/templates/index.php @@ -14,6 +14,7 @@ children()->listed()->sortBy('date', 'desc') as $project): ?> + slideshow()->toFiles(); ?>
  • - 1/images()->count() ?> + 1/count() ?>
    - images() as $image): ?> - $image, - 'srcsetName' => 'project-slideshow', - 'sizes' => '(min-width: 1000px) 50vw, 100vw', - 'lazy' => $image->indexOf() !== 0, - 'class' => $image->indexOf() === 0 ? 'active' : null, - ]) ?> + values() as $i => $slide): ?> + type() === 'video'): ?> + 'video/mp4', + 'm4v' => 'video/mp4', + 'mov' => 'video/mp4', + 'webm' => 'video/webm', + 'ogv' => 'video/ogg', + ]; + $videoType = $videoTypes[strtolower($slide->extension())] ?? $slide->mime(); + ?> + + + $slide, + 'srcsetName' => 'project-slideshow', + 'sizes' => '(min-width: 1000px) 50vw, 100vw', + 'lazy' => $i !== 0, + 'class' => $i === 0 ? 'slide active' : 'slide', + ]) ?> +