Video/GIF en boucle sur l'ecran d'accueil
- Choix d'un media d'accueil dans les parametres Evenement - GIF ou video (MP4/WebM) joue en boucle en fond d'ecran - Import direct depuis le backoffice - Si aucun media, l'animation cercle par defaut est affichee - Le texte (nom evenement, instruction) reste par-dessus Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -3,7 +3,8 @@
|
|||||||
"nom": "Mon Evenement",
|
"nom": "Mon Evenement",
|
||||||
"logo": null,
|
"logo": null,
|
||||||
"couleur_primaire": "#e91e63",
|
"couleur_primaire": "#e91e63",
|
||||||
"couleur_secondaire": "#ffffff"
|
"couleur_secondaire": "#ffffff",
|
||||||
|
"media_accueil": null
|
||||||
},
|
},
|
||||||
"fonctionnalites": {
|
"fonctionnalites": {
|
||||||
"photo_simple": true,
|
"photo_simple": true,
|
||||||
|
|||||||
@@ -52,8 +52,18 @@ html, body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* === Ecran d'accueil === */
|
/* === Ecran d'accueil === */
|
||||||
|
.accueil-media {
|
||||||
|
position: absolute;
|
||||||
|
top: 0; left: 0;
|
||||||
|
width: 100%; height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.accueil-contenu {
|
.accueil-contenu {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
position: relative;
|
||||||
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.accueil-contenu h1 {
|
.accueil-contenu h1 {
|
||||||
|
|||||||
@@ -11,10 +11,13 @@
|
|||||||
|
|
||||||
<!-- Ecran d'accueil -->
|
<!-- Ecran d'accueil -->
|
||||||
<section id="ecran-accueil" class="ecran actif">
|
<section id="ecran-accueil" class="ecran actif">
|
||||||
|
<!-- Fond video/gif en boucle -->
|
||||||
|
<video id="accueil-video" class="accueil-media cache" muted loop playsinline></video>
|
||||||
|
<img id="accueil-gif" class="accueil-media cache">
|
||||||
<div class="accueil-contenu">
|
<div class="accueil-contenu">
|
||||||
<h1 id="nom-evenement">Photobooth</h1>
|
<h1 id="nom-evenement">Photobooth</h1>
|
||||||
<p class="accueil-instruction">Touchez pour commencer</p>
|
<p class="accueil-instruction">Touchez pour commencer</p>
|
||||||
<div class="accueil-animation">
|
<div id="accueil-animation-defaut" class="accueil-animation">
|
||||||
<div class="cercle-pulse"></div>
|
<div class="cercle-pulse"></div>
|
||||||
</div>
|
</div>
|
||||||
<div id="compteur-accueil" class="compteur-accueil cache">
|
<div id="compteur-accueil" class="compteur-accueil cache">
|
||||||
@@ -287,6 +290,17 @@
|
|||||||
<label>Nom de l'evenement</label>
|
<label>Nom de l'evenement</label>
|
||||||
<input type="text" id="admin-nom-event" placeholder="Mon Evenement">
|
<input type="text" id="admin-nom-event" placeholder="Mon Evenement">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="champ">
|
||||||
|
<label>Video/GIF d'accueil (boucle)</label>
|
||||||
|
<div class="champ-row">
|
||||||
|
<select id="admin-media-accueil">
|
||||||
|
<option value="">Aucun (animation par defaut)</option>
|
||||||
|
</select>
|
||||||
|
<button class="btn-secondaire btn-petit" onclick="rafraichirMediaAccueil()">Rafraichir</button>
|
||||||
|
</div>
|
||||||
|
<input type="file" id="input-media-accueil" accept=".gif,.mp4,.webm" class="input-fichier">
|
||||||
|
<button class="btn-secondaire btn-petit" onclick="uploaderMediaAccueil()">Importer</button>
|
||||||
|
</div>
|
||||||
<div class="champ">
|
<div class="champ">
|
||||||
<label>Couleur primaire</label>
|
<label>Couleur primaire</label>
|
||||||
<input type="color" id="admin-couleur-primaire" value="#e91e63">
|
<input type="color" id="admin-couleur-primaire" value="#e91e63">
|
||||||
|
|||||||
@@ -466,11 +466,40 @@ function setupToggleListeners() {
|
|||||||
|
|
||||||
// === EVENEMENT ===
|
// === EVENEMENT ===
|
||||||
|
|
||||||
function chargerEvenementAdmin() {
|
async function chargerEvenementAdmin() {
|
||||||
const event = config.evenement || {};
|
const event = config.evenement || {};
|
||||||
setValue('admin-nom-event', event.nom);
|
setValue('admin-nom-event', event.nom);
|
||||||
setValue('admin-couleur-primaire', event.couleur_primaire || '#e91e63');
|
setValue('admin-couleur-primaire', event.couleur_primaire || '#e91e63');
|
||||||
setValue('admin-couleur-secondaire', event.couleur_secondaire || '#ffffff');
|
setValue('admin-couleur-secondaire', event.couleur_secondaire || '#ffffff');
|
||||||
|
await rafraichirMediaAccueil();
|
||||||
|
const select = document.getElementById('admin-media-accueil');
|
||||||
|
if (event.media_accueil) select.value = event.media_accueil;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function rafraichirMediaAccueil() {
|
||||||
|
const data = await apiGet('/api/animations/custom');
|
||||||
|
const select = document.getElementById('admin-media-accueil');
|
||||||
|
const valeur = select.value;
|
||||||
|
select.innerHTML = '<option value="">Aucun (animation par defaut)</option>';
|
||||||
|
for (const nom of data.tous) {
|
||||||
|
const opt = document.createElement('option');
|
||||||
|
opt.value = nom;
|
||||||
|
opt.textContent = nom;
|
||||||
|
select.appendChild(opt);
|
||||||
|
}
|
||||||
|
if (valeur) select.value = valeur;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function uploaderMediaAccueil() {
|
||||||
|
const input = document.getElementById('input-media-accueil');
|
||||||
|
if (!input.files.length) return;
|
||||||
|
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append('fichier', input.files[0]);
|
||||||
|
await fetch('/api/upload/animation', { method: 'POST', body: formData });
|
||||||
|
input.value = '';
|
||||||
|
await rafraichirMediaAccueil();
|
||||||
|
afficherStatut('Media importe', 'succes');
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sauvegarderEvenement() {
|
async function sauvegarderEvenement() {
|
||||||
@@ -479,8 +508,10 @@ async function sauvegarderEvenement() {
|
|||||||
nom: getValue('admin-nom-event'),
|
nom: getValue('admin-nom-event'),
|
||||||
couleur_primaire: getValue('admin-couleur-primaire'),
|
couleur_primaire: getValue('admin-couleur-primaire'),
|
||||||
couleur_secondaire: getValue('admin-couleur-secondaire'),
|
couleur_secondaire: getValue('admin-couleur-secondaire'),
|
||||||
|
media_accueil: getValue('admin-media-accueil') || null,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
appliquerConfig();
|
||||||
afficherStatut('Evenement sauvegarde', 'succes');
|
afficherStatut('Evenement sauvegarde', 'succes');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,39 @@ function appliquerConfig() {
|
|||||||
toggleVisible('btn-imprimer', fonc.impression);
|
toggleVisible('btn-imprimer', fonc.impression);
|
||||||
toggleVisible('btn-email', fonc.email);
|
toggleVisible('btn-email', fonc.email);
|
||||||
toggleVisible('btn-qr', fonc.qr_code);
|
toggleVisible('btn-qr', fonc.qr_code);
|
||||||
|
|
||||||
|
// Media d'accueil (video/gif en boucle)
|
||||||
|
appliquerMediaAccueil(event.media_accueil);
|
||||||
|
}
|
||||||
|
|
||||||
|
function appliquerMediaAccueil(media) {
|
||||||
|
const video = document.getElementById('accueil-video');
|
||||||
|
const gif = document.getElementById('accueil-gif');
|
||||||
|
const animDefaut = document.getElementById('accueil-animation-defaut');
|
||||||
|
|
||||||
|
// Reset
|
||||||
|
video.classList.add('cache');
|
||||||
|
gif.classList.add('cache');
|
||||||
|
video.pause();
|
||||||
|
video.src = '';
|
||||||
|
gif.src = '';
|
||||||
|
|
||||||
|
if (!media) {
|
||||||
|
// Pas de media, afficher l'animation par defaut
|
||||||
|
animDefaut.classList.remove('cache');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
animDefaut.classList.add('cache');
|
||||||
|
const ext = media.split('.').pop().toLowerCase();
|
||||||
|
|
||||||
|
if (ext === 'gif') {
|
||||||
|
gif.src = `/assets/animations/${media}`;
|
||||||
|
gif.classList.remove('cache');
|
||||||
|
} else {
|
||||||
|
video.src = `/assets/animations/${media}`;
|
||||||
|
video.classList.remove('cache');
|
||||||
|
video.play().catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Navigation ---
|
// --- Navigation ---
|
||||||
|
|||||||
Reference in New Issue
Block a user