feature:fullscreen etc

This commit is contained in:
Frank Meeuwsen 2025-12-21 20:17:29 +01:00
parent 0775ee6161
commit b5faaaae61
7 changed files with 208 additions and 53 deletions

View file

@ -12,12 +12,18 @@ Browser-based interactief workshop spel waarbij deelnemers fysiek kiezen tussen
Een presentatie tool voor workshops waar deelnemers tussen twee stellingen moeten kiezen. De facilitator toont stellingen op een beamer, een timer loopt visueel rond het scherm, en daarna zie je de stellingen grayed out terwijl mensen fysiek naar links/rechts bewegen.
### Features
- Startscherm met controle over startmoment
- Fullscreen modus voor presentaties zonder browser UI
- Timer animatie die synchroon rond het scherm loopt
- Geluidssignaal bij einde timer
- Overlay met stellingen na timer
- Keyboard shortcuts (spatiebalk voor volgende)
- Stelling counter rechtsonder (toont voortgang)
- Keyboard shortcuts (spatiebalk voor volgende, ESC voor fullscreen uit)
- Direct eindscherm bij laatste stelling
- Web-based stellingen editor met Flask backend
- Workshop sets systeem (meerdere configuraties)
- Stellingkast met bibliotheek voor snelle import
- Drag & drop om stellingen te herordenen
- Real-time CRUD operaties op stellingen
- Kleurenpicker voor achtergronden
- Volledig offline werkend
@ -51,12 +57,19 @@ Een presentatie tool voor workshops waar deelnemers tussen twee stellingen moete
### Presentatie Modus
```bash
# Start Flask server (nodig voor config.json laden)
source venv/bin/activate
python server.py
# Open in browser
open index.html
open http://localhost:8000/index.html
```
**Controls:**
- Spatiebalk: Volgende stelling
- Groene "Start IJsbreker" knop om te beginnen
- Fullscreen knop rechtsonder voor volledig scherm
- Spatiebalk: Start spel of ga naar volgende stelling
- ESC: Verlaat fullscreen modus
- Automatische timer animatie
- Geluidssignaal bij einde
@ -228,3 +241,32 @@ Facilitators kunnen nu meerdere workshop configuraties voorbereiden (bijv. versc
- Sets kunnen worden aangemaakt, geladen, gewijzigd en opgeslagen
- Backwards compatible met oude systeem
- Klaar voor productie gebruik
### 2025-12-17 - Fullscreen Modus
**Nieuwe feature:**
- **Fullscreen knop:** Semi-transparante knop rechtsonder (naast counter) om presentatie in volledig scherm te tonen
- **Toggle functionaliteit:** Klik op knop om fullscreen te activeren/deactiveren
- **Visuele feedback:** Icoon draait 180° wanneer in fullscreen modus
- **ESC toets support:** Browser standaard ESC werkt om fullscreen te verlaten
- **Glasmorphism styling:** Moderne semi-transparante knop met blur effect
**Gewijzigde bestanden:**
- `index.html` - Fullscreen knop met SVG icoon toegevoegd
- `style.css` - Styling voor fullscreen button met hover states en is-fullscreen class
- `app.js` - toggleFullscreen() functie, event listeners voor knop en fullscreenchange
- `README.md` - Documentatie bijgewerkt met fullscreen instructies
- `CLAUDE.md` - Features lijst en Session History bijgewerkt
**Waarom:**
Voor workshop presentaties is het belangrijk dat de browser UI (adresbalk, tabs, bookmarks) niet zichtbaar is op de beamer. De fullscreen knop maakt het eenvoudig om de presentatie volledig scherm te tonen zonder browser elementen.
**Hoe het werkt:**
- Gebruikt Fullscreen API (`document.documentElement.requestFullscreen()`)
- Knop blijft zichtbaar in fullscreen modus voor gemakkelijke toggle
- Event listener voor `fullscreenchange` zorgt voor correcte state sync bij ESC toets
- Icoon rotatie geeft visuele feedback over huidige fullscreen state
**Status:**
- Feature volledig werkend en getest
- Documentatie bijgewerkt (README.md en CLAUDE.md)
- Klaar voor gebruik bij workshop presentaties

View file

@ -42,11 +42,13 @@ Hier kun je:
Open in je browser: `http://localhost:8000`
Sluit aan op beamer/groot scherm en:
1. Het spel toont automatisch de eerste stelling
2. Deelnemers lopen naar links of rechts
3. Na de timer: beep + overlay met knop
4. Druk op knop of **spatiebalk** voor volgende stelling
5. Laatste stelling toont direct eindscherm
1. Klik op groene "Start IJsbreker" knop om te beginnen
2. Klik op **fullscreen knop** rechtsonder voor volledig scherm (zonder browser UI)
3. Deelnemers lezen stellingen en lopen naar links of rechts
4. Na de timer: beep + overlay met knop
5. Druk op knop of **spatiebalk** voor volgende stelling
6. Laatste stelling toont direct eindscherm
7. Druk nogmaals op fullscreen knop of **ESC** om fullscreen te verlaten
## Configuratie
@ -83,23 +85,31 @@ Alle instellingen staan in `config.json`:
## Interactie
**Presentatie modus:**
- **Klik op knop**: Ga naar volgende stelling
- **Spatiebalk**: Ga naar volgende stelling (sneller tijdens presentatie)
- **Spatiebalk**: Start spel (op startscherm) of ga naar volgende stelling
- **Fullscreen knop**: Toggle volledig scherm (rechtsonder, naast counter)
- **ESC toets**: Verlaat fullscreen modus
## Features
**Presentatie:**
- ✅ Startscherm met controle over startmoment
- ✅ Fullscreen modus voor presentaties zonder browser UI
- ✅ Visuele timer rondom scherm (loopt synchroon rond)
- ✅ Geluidssignaal bij einde timer
- ✅ Overlay met stellingen na timer (grayed out)
- ✅ Keyboard shortcut (spatiebalk)
- ✅ Stelling counter rechtsonder (toont bijv. "1/8", "2/8")
- ✅ Keyboard shortcuts (spatiebalk voor volgende, ESC voor fullscreen uit)
- ✅ Direct eindscherm bij laatste stelling
**Editor:**
- ✅ Web-based stellingen beheer
- ✅ Workshop sets systeem (meerdere configuraties opslaan en laden)
- ✅ Stellingkast met bibliotheek voor snelle import
- ✅ Drag & drop om stellingen te herordenen
- ✅ Real-time preview van aantal stellingen
- ✅ Kleurenpicker voor achtergronden
- ✅ Drag-free toevoegen/verwijderen
- ✅ Keyboard shortcut (Ctrl/Cmd+S)
- ✅ Validatie van invoer

33
app.js
View file

@ -17,6 +17,7 @@ const startButton = document.getElementById('startButton');
const nextButton = document.getElementById('nextButton');
const finishText = document.getElementById('finishText');
const counterDisplay = document.getElementById('counterDisplay');
const fullscreenButton = document.getElementById('fullscreenButton');
// Laad configuratie bij start
async function loadConfig() {
@ -169,6 +170,25 @@ function playBeep() {
}
}
// Toggle fullscreen modus
function toggleFullscreen() {
if (!document.fullscreenElement) {
// Ga naar fullscreen
document.documentElement.requestFullscreen().then(() => {
fullscreenButton.classList.add('is-fullscreen');
}).catch((error) => {
console.error('Fout bij activeren fullscreen:', error);
});
} else {
// Verlaat fullscreen
document.exitFullscreen().then(() => {
fullscreenButton.classList.remove('is-fullscreen');
}).catch((error) => {
console.error('Fout bij verlaten fullscreen:', error);
});
}
}
// Event listeners
startButton.addEventListener('click', () => {
startGame();
@ -182,6 +202,19 @@ nextButton.addEventListener('click', () => {
}
});
fullscreenButton.addEventListener('click', () => {
toggleFullscreen();
});
// Luister naar fullscreen veranderingen (bijv. via ESC toets)
document.addEventListener('fullscreenchange', () => {
if (document.fullscreenElement) {
fullscreenButton.classList.add('is-fullscreen');
} else {
fullscreenButton.classList.remove('is-fullscreen');
}
});
// Spatiebalk voor volgende stelling EN startscherm
document.addEventListener('keydown', (e) => {
if (e.code === 'Space') {

View file

@ -1,36 +1,40 @@
{
"buttonText": "Volgende",
"buttonText": "Volgende stelling",
"colors": {
"left": "#10b981",
"right": "#f59e0b"
"left": "#3b82f6",
"right": "#ef4444"
},
"finishText": "Bedankt!",
"fontSize": "2.5rem",
"finishText": "Dat was het! Having fun yet?",
"fontSize": "3rem",
"stellingen": [
{
"links": "Inbox Zero held",
"rechts": "1000+ ongelezen mails"
"links": "Koffie",
"rechts": "Thee"
},
{
"links": "Alles digitaal",
"rechts": "Mijn papieren notitieboek is heilig"
"links": "Structurele planner",
"rechts": "Creatieve chaoot"
},
{
"links": "❤️ Mappenstructuur",
"rechts": "❤️ Zoekfunctie"
},
{
"links": "Samenwerken in één document",
"rechts": "Concept_versie_3_def_final.docx mailen"
},
{
"links": "Camera aan tijdens Teams",
"rechts": "Lekker onzichtbaar luisteren"
"links": "Ik gebruik tags en labels",
"rechts": "Ik stop alles in mapjes"
},
{
"links": "Agenda blokken voor focus",
"rechts": "Mijn deur staat altijd open (digitaal)"
"links": "Kennis zit in mijn hoofd",
"rechts": "Kennis staat in het systeem"
},
{
"links": "Ik weet wat de AVG van me vraagt",
"rechts": "Privacy is voor de juristen"
"links": "Ik kom vandaag vooral halen",
"rechts": "Ik kom vandaag ook brengen"
}
],
"timer": 3
"timer": 2
}

View file

@ -18,6 +18,13 @@
<!-- Stelling counter rechtsonder -->
<div id="counterDisplay" class="counter-display hidden"></div>
<!-- Fullscreen knop rechtsonder -->
<button id="fullscreenButton" class="fullscreen-button" title="Volledig scherm">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M8 3H5a2 2 0 0 0-2 2v3m18 0V5a2 2 0 0 0-2-2h-3m0 18h3a2 2 0 0 0 2-2v-3M3 16v3a2 2 0 0 0 2 2h3"/>
</svg>
</button>
<!-- Hoofdcontainer -->
<div id="app" class="container">
<!-- Start scherm -->

View file

@ -1,5 +1,5 @@
{
"activeSetId": "set-1765866890733",
"activeSetId": "set-1765963899829",
"sets": [
{
"config": {
@ -20,37 +20,17 @@
"rechts": "Creatieve chaoot"
},
{
"links": "Ik gebruik meer sneltoetsen",
"rechts": "Ik ben van team muisgebruik"
},
{
"links": "We hebben duidelijke afspraken over naamgeving van bestanden",
"rechts": "Mijn naamgeving van bestanden is veel logischer"
},
{
"links": "Mappenstructuur",
"rechts": "Zoekfunctie"
},
{
"links": "Ik maak eigen notities op één plek",
"rechts": "Ik maak overal notities en zoek me suf"
"links": "❤️ Mappenstructuur",
"rechts": "❤️ Zoekfunctie"
},
{
"links": "Samenwerken in één document",
"rechts": "Concept_versie_3_def_final.docx mailen"
},
{
"links": "Mijn TO-DO lijst is actueel",
"rechts": "Mijn TO-DO lijst is fictie"
},
{
"links": "Ik gebruik tags en labels",
"rechts": "Ik stop alles in mapjes"
},
{
"links": "Browser met 50+ open tabbladen",
"rechts": "Opgeruimde browser"
},
{
"links": "Kennis zit in mijn hoofd",
"rechts": "Kennis staat in het systeem"
@ -106,8 +86,6 @@
"name": "PKM Workshop 2025"
},
{
"id": "set-1765866890733",
"name": "Kerstboom",
"config": {
"buttonText": "Volgende",
"colors": {
@ -143,6 +121,52 @@
}
],
"timer": 3
},
"id": "set-1765866890733",
"name": "Kerstboom"
},
{
"id": "set-1765963899829",
"name": "Korte Pilot sessie",
"config": {
"buttonText": "Volgende stelling",
"colors": {
"left": "#3b82f6",
"right": "#ef4444"
},
"finishText": "Dat was het! Having fun yet?",
"fontSize": "3rem",
"stellingen": [
{
"links": "Koffie",
"rechts": "Thee"
},
{
"links": "Structurele planner",
"rechts": "Creatieve chaoot"
},
{
"links": "❤️ Mappenstructuur",
"rechts": "❤️ Zoekfunctie"
},
{
"links": "Samenwerken in één document",
"rechts": "Concept_versie_3_def_final.docx mailen"
},
{
"links": "Ik gebruik tags en labels",
"rechts": "Ik stop alles in mapjes"
},
{
"links": "Kennis zit in mijn hoofd",
"rechts": "Kennis staat in het systeem"
},
{
"links": "Ik kom vandaag vooral halen",
"rechts": "Ik kom vandaag ook brengen"
}
],
"timer": 2
}
}
]

View file

@ -219,6 +219,41 @@ body {
z-index: 1500;
}
/* Fullscreen knop rechtsonder */
.fullscreen-button {
position: fixed;
bottom: 2rem;
right: 6rem;
width: 3rem;
height: 3rem;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.2);
border: 2px solid rgba(255, 255, 255, 0.4);
border-radius: 8px;
color: white;
cursor: pointer;
transition: all 0.3s ease;
z-index: 1500;
backdrop-filter: blur(10px);
}
.fullscreen-button:hover {
background: rgba(255, 255, 255, 0.3);
border-color: rgba(255, 255, 255, 0.6);
transform: scale(1.1);
}
.fullscreen-button:active {
transform: scale(0.95);
}
/* Fullscreen knop icoon wisselen wanneer in fullscreen */
.fullscreen-button.is-fullscreen svg {
transform: rotate(180deg);
}
/* Helper classes */
.hidden {
display: none !important;