Files
photobooth/frontend/js/effects.js
Jules 77b1127816 Cadre impose visible en overlay sur live + preview + partage
- Overlay cadre sur les 3 ecrans : live (capture), preview (filtres), partage
- chargerCadreImpose() au debut de chaque capture : affiche le cadre event
- Photos sauvegardees sans cadre, cadre applique uniquement a l'impression
- afficherCadreOverlay cherche d'abord dans les cadres evenement

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-23 00:36:57 +02:00

231 lines
7.4 KiB
JavaScript

/* Module effets - Filtres, overlays et fond vert */
let filtreActuel = 'original';
let overlayActuel = null;
let fondActuel = null;
async function chargerFiltres() {
const filtres = await apiGet('/api/filtres');
const barre = document.getElementById('barre-filtres');
barre.innerHTML = '';
for (const [id, nom] of Object.entries(filtres)) {
const btn = document.createElement('button');
btn.className = 'btn-filtre' + (id === 'original' ? ' actif' : '');
btn.textContent = nom;
btn.addEventListener('click', () => appliquerFiltreUI(id, btn));
barre.appendChild(btn);
}
}
async function appliquerFiltreUI(filtre, btn) {
document.querySelectorAll('.btn-filtre').forEach(b => b.classList.remove('actif'));
btn.classList.add('actif');
filtreActuel = filtre;
if (modeActuel === 'multi') {
// En mode multi : ré-assembler le strip avec le filtre appliqué sur chaque photo
await appliquerFiltreStrip(filtre);
return;
}
if (filtre === 'original') {
const chemin = '/data/photos/' + photosSession[0];
document.getElementById('photo-resultat').src = chemin;
document.getElementById('photo-partage').src = chemin;
photoFinale = photosSession[0];
afficherCadreOverlay(cadreChoisi);
return;
}
const resultat = await apiPost('/api/filtre', {
photo: photosSession[0],
filtre: filtre,
});
if (resultat.nom) {
photoFinale = resultat.nom;
document.getElementById('photo-resultat').src = '/data/exports/' + resultat.nom;
document.getElementById('photo-partage').src = '/data/exports/' + resultat.nom;
afficherCadreOverlay(cadreChoisi);
}
}
async function appliquerFiltreStrip(filtre) {
let photosAAssembler = photosSession;
let source = 'photos'; // les originaux sont dans data/photos/
if (filtre !== 'original') {
const promises = photosSession.map(p => apiPost('/api/filtre', { photo: p, filtre }));
const resultats = await Promise.all(promises);
photosAAssembler = resultats.filter(r => r.nom).map(r => r.nom);
source = 'exports'; // les filtrés sont dans data/exports/
if (photosAAssembler.length === 0) return;
}
const mode = config.multi_shot?.mode || 'strip';
const endpoint = mode === 'strip' ? '/api/strip' : '/api/collage';
const resultat = await apiPost(endpoint, { photos: photosAAssembler, source });
if (resultat.nom) {
photoFinale = resultat.nom;
if (resultat.impression) photoImpression = resultat.impression;
const src = '/data/exports/' + resultat.nom;
document.getElementById('photo-resultat').src = src;
document.getElementById('photo-partage').src = src;
afficherCadreOverlay(cadreChoisi);
}
}
function afficherCadreOverlay(nom) {
const ids = ['cadre-overlay-preview', 'cadre-overlay-live', 'cadre-overlay-partage'];
if (!nom) {
ids.forEach(id => {
const el = document.getElementById(id);
if (el) { el.classList.add('cache'); el.src = ''; }
});
return;
}
const config_imp = config.impression || {};
const fmt = (config_imp.format || '15x20').replace('-2up', '');
const event_id = (config.evenement || {}).event_id;
let src = `/assets/cadres/${fmt}/${nom}`;
if (event_id) {
const eventSrc = `/data/evenements/${event_id}/cadres/${fmt}/${nom}`;
src = eventSrc;
}
ids.forEach(id => {
const el = document.getElementById(id);
if (el) {
el.src = src;
el.onerror = () => {
el.src = `/assets/cadres/${fmt}/${nom}`;
el.onerror = null;
};
el.classList.remove('cache');
}
});
}
async function chargerOverlays() {
const overlays = await apiGet('/api/overlays');
const barre = document.getElementById('barre-overlays');
if (overlays.length === 0) {
barre.classList.add('cache');
return;
}
barre.classList.remove('cache');
barre.innerHTML = '';
const btnAucun = document.createElement('button');
btnAucun.className = 'btn-overlay actif';
btnAucun.textContent = 'Sans cadre';
btnAucun.addEventListener('click', () => retirerOverlay(btnAucun));
barre.appendChild(btnAucun);
for (const nom of overlays) {
const btn = document.createElement('button');
btn.className = 'btn-overlay';
btn.textContent = nom.replace('.png', '');
btn.addEventListener('click', () => appliquerOverlayUI(nom, btn));
barre.appendChild(btn);
}
}
async function appliquerOverlayUI(nom, btn) {
document.querySelectorAll('.btn-overlay').forEach(b => b.classList.remove('actif'));
btn.classList.add('actif');
overlayActuel = nom;
const photo = photosSession[0];
const resultat = await apiPost('/api/overlay', { photo, overlay: nom });
if (resultat.nom) {
photoFinale = resultat.nom;
document.getElementById('photo-resultat').src = '/data/exports/' + resultat.nom;
document.getElementById('photo-partage').src = '/data/exports/' + resultat.nom;
}
}
function retirerOverlay(btn) {
document.querySelectorAll('.btn-overlay').forEach(b => b.classList.remove('actif'));
btn.classList.add('actif');
overlayActuel = null;
if (filtreActuel !== 'original') {
appliquerFiltreUI(filtreActuel, document.querySelector('.btn-filtre.actif'));
} else {
const chemin = '/data/photos/' + photosSession[0];
document.getElementById('photo-resultat').src = chemin;
document.getElementById('photo-partage').src = chemin;
photoFinale = photosSession[0];
}
}
// === Fond vert (chroma key) ===
async function chargerFonds() {
const fonds = await apiGet('/api/fonds');
const barre = document.getElementById('barre-fonds');
if (!config.fonctionnalites?.chroma_key || fonds.length === 0) {
barre.classList.add('cache');
return;
}
barre.classList.remove('cache');
barre.innerHTML = '';
fondActuel = null;
// Bouton "original" (pas de chroma key)
const btnOriginal = document.createElement('button');
btnOriginal.className = 'btn-fond actif';
btnOriginal.innerHTML = '<span style="font-size:0.7rem;color:var(--texte-secondaire)">Original</span>';
btnOriginal.addEventListener('click', () => retirerFond(btnOriginal));
barre.appendChild(btnOriginal);
for (const nom of fonds) {
const btn = document.createElement('button');
btn.className = 'btn-fond';
const img = document.createElement('img');
img.src = `/assets/backgrounds/${nom}`;
img.alt = nom;
btn.appendChild(img);
btn.addEventListener('click', () => appliquerFondUI(nom, btn));
barre.appendChild(btn);
}
}
async function appliquerFondUI(nom, btn) {
document.querySelectorAll('.btn-fond').forEach(b => b.classList.remove('actif'));
btn.classList.add('actif');
fondActuel = nom;
const photo = photosSession[0];
const resultat = await apiPost('/api/chroma', { photo, fond: nom });
if (resultat.nom) {
photoFinale = resultat.nom;
document.getElementById('photo-resultat').src = '/data/exports/' + resultat.nom;
document.getElementById('photo-partage').src = '/data/exports/' + resultat.nom;
}
}
function retirerFond(btn) {
document.querySelectorAll('.btn-fond').forEach(b => b.classList.remove('actif'));
btn.classList.add('actif');
fondActuel = null;
// Revenir a la photo originale ou avec filtre
if (filtreActuel !== 'original') {
appliquerFiltreUI(filtreActuel, document.querySelector('.btn-filtre.actif'));
} else {
const chemin = '/data/photos/' + photosSession[0];
document.getElementById('photo-resultat').src = chemin;
document.getElementById('photo-partage').src = chemin;
photoFinale = photosSession[0];
}
}