Init photobooth - borne photo evenementielle RPi4
Backend FastAPI complet : camera gphoto2, filtres/overlays Pillow, chroma key OpenCV, multi-shot/collage, GIF, impression CUPS, email SMTP, QR code. Frontend web vanilla (HTML/CSS/JS) pour Chromium kiosk. Menu admin cache (appui long coin ecran). Toutes les fonctionnalites activables/desactivables. Scripts install + systemd pour RPi4. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
103
frontend/js/effects.js
vendored
Normal file
103
frontend/js/effects.js
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
/* Module effets - Filtres et overlays */
|
||||
|
||||
let filtreActuel = 'original';
|
||||
let overlayActuel = 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) {
|
||||
// Activer visuellement
|
||||
document.querySelectorAll('.btn-filtre').forEach(b => b.classList.remove('actif'));
|
||||
btn.classList.add('actif');
|
||||
filtreActuel = filtre;
|
||||
|
||||
if (filtre === 'original') {
|
||||
const chemin = '/data/photos/' + photosSession[0];
|
||||
document.getElementById('photo-resultat').src = chemin;
|
||||
document.getElementById('photo-partage').src = chemin;
|
||||
photoFinale = photosSession[0];
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 = '';
|
||||
|
||||
// Bouton "sans overlay"
|
||||
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;
|
||||
|
||||
// Revenir a la photo avec filtre actuel (ou originale)
|
||||
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];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user