Index > Fix vidéos non prise en charges dans le slider
All checks were successful
Deploy / Deploy to Production (push) Successful in 5s

This commit is contained in:
Camilledenoray 2026-06-17 12:25:23 +02:00
parent c92e492fbc
commit 9a615bd92d
7 changed files with 97 additions and 81 deletions

View file

@ -31,7 +31,7 @@ body[data-template="index"] {
section.toggle { section.toggle {
.project-slideshow { .project-slideshow {
picture:not(.active) { .slide:not(.active) {
display: none; display: none;
} }
} }

View file

@ -121,7 +121,8 @@ button#mobile-menu-toggle {
right: 0; right: 0;
position: absolute; position: absolute;
picture img { picture img,
video.slide {
max-width: 100%; max-width: 100%;
max-height: calc(100vh - var(--body-margin) * 2); max-height: calc(100vh - var(--body-margin) * 2);
vertical-align: bottom; vertical-align: bottom;

View file

@ -26,14 +26,16 @@
inset: 0; inset: 0;
width: auto; width: auto;
height: auto; height: auto;
picture { picture,
video.slide {
inset: 0; inset: 0;
position: absolute; position: absolute;
img { }
width: 100%; picture img,
height: 100%; video.slide {
object-fit: cover; width: 100%;
} height: 100%;
object-fit: cover;
} }
} }

View file

@ -121,7 +121,8 @@ button#mobile-menu-toggle {
right: 0; right: 0;
position: absolute; position: absolute;
} }
.project-slideshow picture img { .project-slideshow picture img,
.project-slideshow video.slide {
max-width: 100%; max-width: 100%;
max-height: calc(100vh - var(--body-margin) * 2); max-height: calc(100vh - var(--body-margin) * 2);
vertical-align: bottom; vertical-align: bottom;
@ -586,7 +587,7 @@ body[data-template=index] .filter-menu ul {
body[data-template=index] .projects-index li.filtered-out { body[data-template=index] .projects-index li.filtered-out {
display: none; 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; display: none;
} }
body[data-template=index] ul.projects-index { body[data-template=index] ul.projects-index {
@ -621,11 +622,13 @@ body[data-template=index] ul.projects-index {
width: auto; width: auto;
height: auto; height: auto;
} }
.project-slideshow picture { .project-slideshow picture,
.project-slideshow video.slide {
inset: 0; inset: 0;
position: absolute; position: absolute;
} }
.project-slideshow picture img { .project-slideshow picture img,
.project-slideshow video.slide {
width: 100%; width: 100%;
height: 100%; height: 100%;
-o-object-fit: cover; -o-object-fit: cover;

View file

@ -7,116 +7,104 @@ document.addEventListener("DOMContentLoaded", () => {
const firstProject = projects[0]; const firstProject = projects[0];
const lastProject = projects[projects.length - 1]; const lastProject = projects[projects.length - 1];
const firstPictureFirstProject = firstProject.querySelector( // Première / dernière slide d'un projet (image OU vidéo).
".project-slideshow picture:first-of-type", // On cible la classe « .slide » au lieu de la balise « picture »
); // pour que les vidéos comptent comme des slides normales.
const firstPictureLastProject = lastProject.querySelector( const firstSlide = (project) =>
".project-slideshow picture:first-of-type", project.querySelector(".project-slideshow > .slide");
); const lastSlide = (project) => {
const lastPictureLastProject = lastProject.querySelector( const slides = project.querySelectorAll(".project-slideshow > .slide");
".project-slideshow picture:last-of-type", 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 // Fonctions de navigation : les éléments « courants » sont re-requêtés
// à chaque appel pour refléter l'état actuel du DOM. // à chaque appel pour refléter l'état actuel du DOM.
function goToNextPicture() { 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 selectedProject = document.querySelector(".project.selected");
const nextProject = selectedProject.nextElementSibling; const activeSlide = selectedProject.querySelector(
const firstPictureNextProject = nextProject?.querySelector( ".project-slideshow > .slide.active",
".project-slideshow picture:first-of-type",
); );
const lastSlideSelected = lastSlide(selectedProject);
const nextProject = selectedProject.nextElementSibling;
if (activePicture !== lastPicture) { if (activeSlide !== lastSlideSelected) {
activePicture.classList.remove("active"); activeSlide.classList.remove("active");
activePicture.nextElementSibling.classList.add("active"); activeSlide.nextElementSibling.classList.add("active");
} else { } else {
selectedProject.classList.remove("selected"); selectedProject.classList.remove("selected");
activePicture.classList.remove("active"); activeSlide.classList.remove("active");
if (selectedProject !== lastProject) { if (selectedProject !== lastProject) {
nextProject.classList.add("selected"); nextProject.classList.add("selected");
firstPictureNextProject.classList.add("active"); firstSlide(nextProject).classList.add("active");
} else { } else {
firstProject.classList.add("selected"); firstProject.classList.add("selected");
firstPictureFirstProject.classList.add("active"); firstSlideFirstProject.classList.add("active");
} }
} }
} }
function goToPrevPicture() { 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 selectedProject = document.querySelector(".project.selected");
const prevProject = selectedProject.previousElementSibling; const activeSlide = selectedProject.querySelector(
const lastPicturePrevProject = prevProject?.querySelector( ".project-slideshow > .slide.active",
".project-slideshow picture:last-of-type",
); );
const firstSlideSelected = firstSlide(selectedProject);
const prevProject = selectedProject.previousElementSibling;
if (activePicture !== firstPicture) { if (activeSlide !== firstSlideSelected) {
activePicture.classList.remove("active"); activeSlide.classList.remove("active");
activePicture.previousElementSibling.classList.add("active"); activeSlide.previousElementSibling.classList.add("active");
} else { } else {
selectedProject.classList.remove("selected"); selectedProject.classList.remove("selected");
activePicture.classList.remove("active"); activeSlide.classList.remove("active");
if (selectedProject !== firstProject) { if (selectedProject !== firstProject) {
prevProject.classList.add("selected"); prevProject.classList.add("selected");
lastPicturePrevProject.classList.add("active"); lastSlide(prevProject).classList.add("active");
} else { } else {
lastProject.classList.add("selected"); lastProject.classList.add("selected");
lastPictureLastProject.classList.add("active"); lastSlideLastProject.classList.add("active");
} }
} }
} }
function goToPrevProject() { function goToPrevProject() {
const activePicture = document.querySelector(
".project.selected .project-slideshow > picture.active",
);
const selectedProject = document.querySelector(".project.selected"); const selectedProject = document.querySelector(".project.selected");
const prevProject = selectedProject.previousElementSibling; const activeSlide = selectedProject.querySelector(
const firstPicturePrevProject = prevProject?.querySelector( ".project-slideshow > .slide.active",
".project-slideshow picture:first-of-type",
); );
const prevProject = selectedProject.previousElementSibling;
activePicture.classList.remove("active"); activeSlide.classList.remove("active");
selectedProject.classList.remove("selected"); selectedProject.classList.remove("selected");
if (selectedProject !== firstProject) { if (selectedProject !== firstProject) {
prevProject.classList.add("selected"); prevProject.classList.add("selected");
firstPicturePrevProject.classList.add("active"); firstSlide(prevProject).classList.add("active");
} else { } else {
lastProject.classList.add("selected"); lastProject.classList.add("selected");
firstPictureLastProject.classList.add("active"); firstSlideLastProject.classList.add("active");
} }
} }
function goToNextProject() { function goToNextProject() {
const activePicture = document.querySelector(
".project.selected .project-slideshow > picture.active",
);
const selectedProject = document.querySelector(".project.selected"); const selectedProject = document.querySelector(".project.selected");
const nextProject = selectedProject.nextElementSibling; const activeSlide = selectedProject.querySelector(
const firstPictureNextProject = nextProject?.querySelector( ".project-slideshow > .slide.active",
".project-slideshow picture:first-of-type",
); );
const nextProject = selectedProject.nextElementSibling;
activePicture.classList.remove("active"); activeSlide.classList.remove("active");
selectedProject.classList.remove("selected"); selectedProject.classList.remove("selected");
if (selectedProject !== lastProject) { if (selectedProject !== lastProject) {
nextProject.classList.add("selected"); nextProject.classList.add("selected");
firstPictureNextProject.classList.add("active"); firstSlide(nextProject).classList.add("active");
} else { } else {
firstProject.classList.add("selected"); firstProject.classList.add("selected");
firstPictureFirstProject.classList.add("active"); firstSlideFirstProject.classList.add("active");
} }
} }

View file

@ -22,9 +22,11 @@ allProjects.forEach((currentProject) => {
}); });
currentProject currentProject
.querySelectorAll("picture") .querySelectorAll(".project-slideshow > .slide")
.forEach((picture) => picture.classList.remove("active")); .forEach((slide) => slide.classList.remove("active"));
currentProject.querySelector("picture:first-child").classList.add("active"); currentProject
.querySelector(".project-slideshow > .slide")
.classList.add("active");
currentProject.classList.toggle("selected"); currentProject.classList.toggle("selected");
Router.setParam("project", currentProject.dataset.slug); Router.setParam("project", currentProject.dataset.slug);

View file

@ -14,6 +14,7 @@
</li> </li>
<?php foreach ($page->children()->listed()->sortBy('date', 'desc') as $project): ?> <?php foreach ($page->children()->listed()->sortBy('date', 'desc') as $project): ?>
<?php $slides = $project->slideshow()->toFiles(); ?>
<li class="project" data-category="<?= Str::slug($project->category()) ?>" data-slug="<?= $project->slug() ?>"> <li class="project" data-category="<?= Str::slug($project->category()) ?>" data-slug="<?= $project->slug() ?>">
<div class="fix"> <div class="fix">
<button class="project-toggler grid"> <button class="project-toggler grid">
@ -21,20 +22,39 @@
<span> <?= $project->tags() ?> </span> <span> <?= $project->tags() ?> </span>
<span class="date"> <?= $project->date()->toDate('Y') ?> </span> <span class="date"> <?= $project->date()->toDate('Y') ?> </span>
</button> </button>
<span class="slide-number"><span class="current-image">1</span>/<?= $project->images()->count() ?></span> <span class="slide-number"><span class="current-image">1</span>/<?= $slides->count() ?></span>
</div> </div>
<section class="toggle"> <section class="toggle">
<div class= "project-slideshow-container"> <div class= "project-slideshow-container">
<button class="closer"></button> <button class="closer"></button>
<div class="project-slideshow"> <div class="project-slideshow">
<?php foreach ($project->images() as $image): ?> <?php foreach ($slides->values() as $i => $slide): ?>
<?php snippet('picture', [ <?php if ($slide->type() === 'video'): ?>
'file' => $image, <?php
'srcsetName' => 'project-slideshow', // Type web fiable basé sur l'extension : le mime() de Kirby
'sizes' => '(min-width: 1000px) 50vw, 100vw', // peut renvoyer video/quicktime pour un .mp4 (fichier .mov
'lazy' => $image->indexOf() !== 0, // renommé), ce que Chrome/Firefox refusent de lire.
'class' => $image->indexOf() === 0 ? 'active' : null, $videoTypes = [
]) ?> 'mp4' => 'video/mp4',
'm4v' => 'video/mp4',
'mov' => 'video/mp4',
'webm' => 'video/webm',
'ogv' => 'video/ogg',
];
$videoType = $videoTypes[strtolower($slide->extension())] ?? $slide->mime();
?>
<video class="slide<?= $i === 0 ? ' active' : '' ?>" autoplay muted loop playsinline data-id="<?= $slide->uuid() ?>">
<source src="<?= $slide->url() ?>" type="<?= $videoType ?>">
</video>
<?php else: ?>
<?php snippet('picture', [
'file' => $slide,
'srcsetName' => 'project-slideshow',
'sizes' => '(min-width: 1000px) 50vw, 100vw',
'lazy' => $i !== 0,
'class' => $i === 0 ? 'slide active' : 'slide',
]) ?>
<?php endif ?>
<?php endforeach; ?> <?php endforeach; ?>
<button class="prev"></button> <button class="prev"></button>
<button class="next"></button> <button class="next"></button>