Ajout d'un exemple d'utilisation de vCarousel associé à Flickity (carrousel d'images).

This commit is contained in:
Fabrice PENHOËT 2021-04-08 12:41:47 +02:00
parent 3ec8ecbd65
commit 4d3ed007c0
14 changed files with 252 additions and 40 deletions

View File

@ -9,6 +9,7 @@ Lorsque la lecture d'une vidéo est achevée, elle disparaît pour faire appara
Il ne s'agit donc pas d'un carrousel servant à faire défiler horizontalement des balises vidéos.
Mais on peut très bien utiliser ce type de carrousel en parallèle pour naviguer entre les vidéos.
Un exemple d'utilisation avec [Flickity](https://www.npmjs.com/package/flickity) est fourni.
## Les grandes lignes de l'algorithme

52
package-lock.json generated
View File

@ -1296,6 +1296,11 @@
"minimalistic-assert": "^1.0.0"
}
},
"desandro-matches-selector": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/desandro-matches-selector/-/desandro-matches-selector-2.0.2.tgz",
"integrity": "sha1-cXvu1NwT59jzdi9wem1YpndCGOE="
},
"destroy": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
@ -1515,6 +1520,11 @@
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
"dev": true
},
"ev-emitter": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ev-emitter/-/ev-emitter-1.1.1.tgz",
"integrity": "sha512-ipiDYhdQSCZ4hSbX4rMW+XzNKMD1prg/sTvoVmSLkuQ1MVlwjJQQA+sW8tMYR3BLUr9KjodFV4pvzunvRhd33Q=="
},
"eventemitter3": {
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
@ -1834,6 +1844,27 @@
"resolve-dir": "^1.0.1"
}
},
"fizzy-ui-utils": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/fizzy-ui-utils/-/fizzy-ui-utils-2.0.7.tgz",
"integrity": "sha512-CZXDVXQ1If3/r8s0T+v+qVeMshhfcuq0rqIFgJnrtd+Bu8GmDmqMjntjUePypVtjHXKJ6V4sw9zeyox34n9aCg==",
"requires": {
"desandro-matches-selector": "^2.0.0"
}
},
"flickity": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/flickity/-/flickity-2.2.2.tgz",
"integrity": "sha512-yiPMuP8tw/zN7ARgeSLZNvzK11GkzI2mp/zlYBsyttguSCROAqxj6wiN2sSfPfW3xMG3hcUHxWUXNQMlk/wYcg==",
"requires": {
"desandro-matches-selector": "^2.0.0",
"ev-emitter": "^1.1.1",
"fizzy-ui-utils": "^2.0.7",
"get-size": "^2.0.3",
"unidragger": "^2.3.0",
"unipointer": "^2.3.0"
}
},
"flush-write-stream": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
@ -1935,6 +1966,11 @@
"has-symbols": "^1.0.1"
}
},
"get-size": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/get-size/-/get-size-2.0.3.tgz",
"integrity": "sha512-lXNzT/h/dTjTxRbm9BXb+SGxxzkm97h/PCIKtlN/CBCxxmkkIVV21udumMS93MuVTDX583gqc94v3RjuHmI+2Q=="
},
"get-stream": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
@ -4575,6 +4611,14 @@
"integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==",
"dev": true
},
"unidragger": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/unidragger/-/unidragger-2.3.1.tgz",
"integrity": "sha512-u+IgG7AG0MXJTKcdzAIYxCm+W5FcnA9M28203Awl6jIcE3/+9OtEyUX4Wv64y7XNKEVRKPot52IV4V6x7FlF5Q==",
"requires": {
"unipointer": "^2.3.0"
}
},
"union-value": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
@ -4587,6 +4631,14 @@
"set-value": "^2.0.1"
}
},
"unipointer": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/unipointer/-/unipointer-2.3.0.tgz",
"integrity": "sha512-m85sAoELCZhogI1owtJV3Dva7GxkHk2lI7A0otw3o0OwCuC/Q9gi7ehddigEYIAYbhkqNdri+dU1QQkrcBvirQ==",
"requires": {
"ev-emitter": "^1.0.1"
}
},
"unique-filename": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",

View File

@ -1,6 +1,6 @@
{
"name": "vCarousel",
"version": "0.1.0",
"version": "0.2.0",
"description": "Video carousel, a new video appears when the previous one finishes playing.",
"main": "index.js",
"scripts": {
@ -24,5 +24,8 @@
"webpack": "^4.46.0",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.2"
},
"dependencies": {
"flickity": "^2.2.2" // dépendance pouvant être retirée si vous n'utilisez pas Flickity dans votre application
}
}

4
public/CSS/flickity.min.css vendored Normal file
View File

@ -0,0 +1,4 @@
/*! Flickity v2.2.2
https://flickity.metafizzy.co
---------------------------------------------- */
.flickity-enabled{position:relative}.flickity-enabled:focus{outline:0}.flickity-viewport{overflow:hidden;position:relative;height:100%}.flickity-slider{position:absolute;width:100%;height:100%}.flickity-enabled.is-draggable{-webkit-tap-highlight-color:transparent;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.flickity-enabled.is-draggable .flickity-viewport{cursor:move;cursor:-webkit-grab;cursor:grab}.flickity-enabled.is-draggable .flickity-viewport.is-pointer-down{cursor:-webkit-grabbing;cursor:grabbing}.flickity-button{position:absolute;background:hsla(0,0%,100%,.75);border:none;color:#333}.flickity-button:hover{background:#fff;cursor:pointer}.flickity-button:focus{outline:0;box-shadow:0 0 0 5px #19f}.flickity-button:active{opacity:.6}.flickity-button:disabled{opacity:.3;cursor:auto;pointer-events:none}.flickity-button-icon{fill:currentColor}.flickity-prev-next-button{top:50%;width:44px;height:44px;border-radius:50%;transform:translateY(-50%)}.flickity-prev-next-button.previous{left:10px}.flickity-prev-next-button.next{right:10px}.flickity-rtl .flickity-prev-next-button.previous{left:auto;right:10px}.flickity-rtl .flickity-prev-next-button.next{right:auto;left:10px}.flickity-prev-next-button .flickity-button-icon{position:absolute;left:20%;top:20%;width:60%;height:60%}.flickity-page-dots{position:absolute;width:100%;bottom:-25px;padding:0;margin:0;list-style:none;text-align:center;line-height:1}.flickity-rtl .flickity-page-dots{direction:rtl}.flickity-page-dots .dot{display:inline-block;width:10px;height:10px;margin:0 8px;background:#333;border-radius:50%;opacity:.25;cursor:pointer}.flickity-page-dots .dot.is-selected{opacity:1}

21
public/CSS/vcarousel.css Normal file
View File

@ -0,0 +1,21 @@
body
{
text-align:center;
background-color:#C0D6D2;
}
#videos
{
border:1px solid;
width:800px;
margin:auto;
padding:1em;
text-align:center;
}
#video figure
{
padding-top:2em;
}
#videos video
{
width:600px;
}

48
public/flickity.html Normal file
View File

@ -0,0 +1,48 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Page d'exemple pour le script vCarousel avec un menu utilisant Flickity.">
<meta name="robots" content="noindex">
<link rel="stylesheet" href="CSS/vcarousel.css" media="screen">
<link rel="stylesheet" href="CSS/flickity.min.css" media="screen">
<script src="JS/exampleFlickity.app.js" defer></script>
<title>vCarousel (démo avec Flickity)</title>
</head>
<body>
<div id="videos">
<h1 id="title">vCarousel</h1>
<p>Dans cet exemple vCarousel est associé à un carrousel d'images plus classique gèré via <a href="https://flickity.metafizzy.co/" target="_blank" rel="noopener">flickity</a> servant de menu pour choisir la première vidéo à visionner. Ensuite vCarousel enchaîne les vidéos et synchronise l'affichage de flickity.</p>
<figure id="vFunanbule">
<video controls preload="metadata">
<source src="videos/Lizio-Poete-Ferrailleur-clownfunanbule.m4v" type="video/mp4"></source>
<p>Votre navigateur ne prend pas en charge les vidéos HTML5.</p>
</video>
<figcaption>Un clown funanbule !</figcaption>
</figure>
<figure id="vForgeron">
<video controls preload="metadata">
<source src="videos/Lizio-Poete-Ferrailleur-forgeron.m4v" type="video/mp4"></source>
<p>Votre navigateur ne prend pas en charge les vidéos HTML5.</p>
</video>
<figcaption>Il faut forger pour devenir forgeron !</figcaption>
</figure>
<figure id="vCircuit">
<video controls preload="metadata">
<source src="videos/Lizio-Poete-Ferrailleur-drole-de-circuit.m4v" type="video/mp4"></source>
<p>Votre navigateur ne prend pas en charge les vidéos HTML5.</p>
</video>
<figcaption>Drôle de circuit !</figcaption>
</figure>
<nav class="img-carousel">
<div class="carousel-cell"><a href="#vFunanbule" class="selectVideo"><img src="img/clownfunanbule.png" alt="Le funanbule"></a></div>
<div class="carousel-cell"><a href="#vForgeron" class="selectVideo"><img src="img/forgeron.png" alt="Le forgeron"></a></div>
<div class="carousel-cell"><a href="#vCircuit" class="selectVideo"><img src="img/drole-de-circuit.png" alt="Le drôle de circuit"></a></div>
</nav>
</div>
<aside><p>Les courtes vidéos de cette page d'exemple ont été enregistrées le 11 août 2016 au <a href="https://www.poeteferrailleur.com/" target="_blank">Poète ferrailleur</a> à Lizio dans le Morbihan.</p></aside>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
public/img/forgeron.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@ -2,43 +2,48 @@
<html>
<head>
<meta charset="utf-8">
<title>vCarousel (démo)</title>
<meta name="description" content="Page d'exemple pour le script vCarousel.">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="Page d'exemple simple d'utilisaion du script vCarousel.">
<meta name="robots" content="noindex">
<link rel="stylesheet" href="CSS/vcarousel.css" media="screen">
<script src="JS/example.app.js" defer></script>
<title>vCarousel (démo utilisation simple)</title>
</head>
<body>
<h1 id="title">vCarousel</h1>
<p>Lorsqu'une vidéo se termine, la suivante la remplace, prête à être lancée.</p>
<figure id="vFunanbule">
<video controls="controls" preload="metadata" width="800">
<source src="videos/Lizio-Poete-Ferrailleur-clownfunanbule.m4v" type="video/mp4"></source>
<p>Votre navigateur ne prend pas en charge les vidéos HTML5.</p>
</video>
<figcaption>Un clown funanbule !</figcaption>
</figure>
<figure id="vForgeron">
<video controls="controls" preload="metadata" width="800">
<source src="videos/Lizio-Poete-Ferrailleur-forgeron.m4v" type="video/mp4"></source>
<p>Votre navigateur ne prend pas en charge les vidéos HTML5.</p>
</video>
<figcaption>Il faut forger pour devenir forgeron !</figcaption>
</figure>
<figure id="vCircuit">
<video controls="controls" preload="metadata" width="800">
<source src="videos/Lizio-Poete-Ferrailleur-drole-de-circuit.m4v" type="video/mp4"></source>
<p>Votre navigateur ne prend pas en charge les vidéos HTML5.</p>
</video>
<figcaption>Drôle de circuit !</figcaption>
</figure>
<nav>
<h3>Au menu</h3>
<ul>
<li><a href="#vFunanbule" class="selectVideo">Le funanbule</a></li>
<li><a href="#vForgeron" class="selectVideo">Le forgeron</a></li>
<li><a href="#vCircuit" class="selectVideo">Le circuit</a></li>
</ul>
</nav>
<aside><p>Les courtes vidéos de cette page d'exemple ont été enregistrées le 11 août 2016 au <a href="https://www.poeteferrailleur.com/">Poète ferrailleur</a> à Lizio dans le Morbihan.</p></aside>
<div id="videos">
<h1>vCarousel</h1>
<p>Exemple d'utilisation simple : lorsqu'une vidéo se termine, la suivante la remplace, prête à être lancée. <a href="/flickity.html">Voir un autre exemple d'utilisation où VCarousel est associé à un carrousel d'images</a>.</p>
<figure id="vFunanbule">
<video controls="controls" preload="metadata" width="800">
<source src="videos/Lizio-Poete-Ferrailleur-clownfunanbule.m4v" type="video/mp4"></source>
<p>Votre navigateur ne prend pas en charge les vidéos HTML5.</p>
</video>
<figcaption>Un clown funanbule !</figcaption>
</figure>
<figure id="vForgeron">
<video controls="controls" preload="metadata" width="800">
<source src="videos/Lizio-Poete-Ferrailleur-forgeron.m4v" type="video/mp4"></source>
<p>Votre navigateur ne prend pas en charge les vidéos HTML5.</p>
</video>
<figcaption>Il faut forger pour devenir forgeron !</figcaption>
</figure>
<figure id="vCircuit">
<video controls="controls" preload="metadata" width="800">
<source src="videos/Lizio-Poete-Ferrailleur-drole-de-circuit.m4v" type="video/mp4"></source>
<p>Votre navigateur ne prend pas en charge les vidéos HTML5.</p>
</video>
<figcaption>Drôle de circuit !</figcaption>
</figure>
<nav>
<h3>Au menu</h3>
<ul>
<li><a href="#vFunanbule" class="selectVideo">Le funanbule</a></li>
<li><a href="#vForgeron" class="selectVideo">Le forgeron</a></li>
<li><a href="#vCircuit" class="selectVideo">Le circuit</a></li>
</ul>
</nav>
</div>
<aside><p>Les courtes vidéos de cette page d'exemple ont été enregistrées le 11 août 2016 au <a href="https://www.poeteferrailleur.com/" target="_blank">Poète ferrailleur</a> à Lizio dans le Morbihan.</p></aside>
</body>
</html>

View File

@ -1,15 +1,15 @@
/// Exemple d'utilisation de vCarousel avec 3 vidéos
/// Exemple d'utilisation simple de vCarousel avec 3 vidéos
import { vCarousel } from "./vCarousel";
try
{
// Liste des id des contenants des vidéos à afficher :
// Liste des id des contenants des vidéos à faire tourner :
const videosContainers=["vFunanbule", "vForgeron", "vCircuit"];
// Si un id est fourni par l'url, on affiche cette vidéo en premier :
if(window.location.hash!==undefined && window.location.hash!=="")
vCarousel(videosContainers, window.location.hash.replace("#",""));
else
vCarousel(videosContainers);// le deuxième paramètre est facultatif sauf si on souhaite qu'une des vidéos soit affichée par défaut
vCarousel(videosContainers);// le deuxième paramètre est facultatif, sauf si on souhaite qu'une vidéo autre que la première soit affichée par défaut
// Dans le cas où l'utilisateur clique pour sélectionner une vidéo à afficher, on actualise l'affichage :
let selectLinks=document.querySelectorAll(".selectVideo");

76
src/exampleFlickity.ts Normal file
View File

@ -0,0 +1,76 @@
/// Exemple d'utilisation de vCarousel avec 3 vidéos, proposées via un carrousel d'images Flickity
const Flickity = require("flickity");
import { vCarousel } from "./vCarousel";
// Cette fonction sert à synchroniser si besoin l'image sélectionnée dans le carrousel Flickity avec le hash de l'url.
const selectFlickityForHash = (flickityCarousel:any, urlHash:string) : void =>
{
let nb=0, find=false;
// On parcourt les items du carrousel pour trouver celui contenant le lien vers ce hash.
for(let cel of flickityCarousel.cells)
{
let childrens = cel.element.childNodes;
for (let i = 0, c = childrens.length; i < c; i++)
{
if (childrens[i].nodeType === Node.ELEMENT_NODE)
{
if(childrens[i].hash!=undefined && childrens[i].hash===urlHash)
{
flickityCarousel.select(nb);// API Flickity : https://flickity.metafizzy.co/api.html
find=true;
break;
}
}
}
nb++;
}
if(find===false)
console.error("L'ancre fournie par l'url n'a pas été trouvée dans le carrousel Flickity.");
}
try
{
// Carrousel Flickity :
const imgCarousel = document.querySelector(".img-carousel");
const flktyCarousel = new Flickity(imgCarousel,
{
// options : https://flickity.metafizzy.co/options.html
accessibility: true,
cellAlign: "center",
contain: true,
rightToLeft: true,
wrapAround: true,
});
// Liste des id des contenants des vidéos à faire tourner :
const videosContainers=["vFunanbule", "vForgeron", "vCircuit"];
// Si un id est fourni par l'url, on affiche cette vidéo en premier :
if(window.location.hash!==undefined && window.location.hash!=="")
{
vCarousel(videosContainers, window.location.hash.replace("#",""));
selectFlickityForHash(flktyCarousel, location.hash);
}
else
vCarousel(videosContainers, ""); // dans cet exemple, on cache toutes les vidéos avant que l'utilisateur ne fasse son choix dans le carrousel d'images.
// Lorsque l'utilisateur clique sur une des images pour sélectionner une vidéo à afficher, on actualise l'affichage :
let selectLinks=document.querySelectorAll(".selectVideo");
for (let i = 0; i < selectLinks.length; i++)
{
let link=<HTMLAnchorElement>selectLinks[i];
link.addEventListener("click", function(e)
{
vCarousel(videosContainers, link.hash.replace("#",""));
});
}
// De même quand le hash change, on adapte l'item sélectionné de flickity
// Ceci permet de suivre le parcours des vidéos par vCarousel
window.addEventListener('hashchange', function()
{
selectFlickityForHash(flktyCarousel, location.hash);
});
}
catch(e)
{
console.error(e);
}

View File

@ -1,9 +1,10 @@
const Flickity = require("flickity");
/// La fonction vCarousel reçoit un tableau d'ids des conteneurs HTML des vidéos à afficher successivement.
/// Le tableau n'est pas dédoublonné, pour rester libre d'afficher plusieurs fois la même vidéo durant un tour du carrousel.
/// On peut éventuellement fournir l'id du conteneur de la première vidéo à afficher lors de l'appel
/// Ou encore indiqué qu'aucune ne doit être affichée sans action en passant une chaîne vide
/// Par défaut la première vidéo de la liste sera affichée
export const vCarousel = (vContainers:string[], firstVideoId?:string) : void =>
{
interface videoDOM

View File

@ -6,7 +6,8 @@ module.exports =
devtool: "inline-source-map",
entry:
{
example: "./src/example.ts"
example: "./src/example.ts",
exampleFlickity: "./src/exampleFlickity.ts"
},
output:
{