Changeset e679bce in Klonkt for src/assets/js/mod/tape.js
- Timestamp:
- 08/22/2026 09:54:51 AM (3 weeks ago)
- Branches:
- main
- Children:
- 8bb3b09
- Parents:
- 16fd4fe
- File:
-
- 1 edited
-
src/assets/js/mod/tape.js (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/assets/js/mod/tape.js
r16fd4fe re679bce 7 7 * een bandgevoel na te doen zou twee dingen tegelijk laten klinken en die hele 8 8 * sessie weggooien. Dus: de afspeelknop draagt dezelfde data-attributen als een 9 * albumhoes en wordt door die speler opgepakt , en spoelen is next()/prev().9 * albumhoes en wordt door die speler opgepakt. 10 10 * 11 * DAAROM SPOELT HET PER NUMMER en niet per seconde. Die speler denkt in een 12 * wachtrij. Dat is een eerlijke benadering van een cassette: je komt vooruit en 13 * achteruit, en je springt niet naar nummer zeven. 11 * SPOELEN GAAT IN SECONDEN, over de nummergrenzen heen. Dat kan omdat die 12 * speler een wachtrij in EEN doorlopende MediaSource-tijdlijn giet: "een 13 * trackwissel is een positie, geen omschakeling". Een bandje is dus letterlijk 14 * die tijdlijn. Vandaar seekBy() en niet next()/prev() -- springen per nummer 15 * is een playlistgebaar, en dan is dit een lijst met een cassetteplaatje. 14 16 * 15 17 * WAAROM ER GEPOLLD WORDT. audio-player.js zendt geen gebeurtenissen uit -- het … … 76 78 } 77 79 80 /** 81 * SPOELEN IS VASTHOUDEN, en dat is het verschil met een afspeellijst. 82 * 83 * Eerst deed vooruit en achteruit hier next()/prev(): een nummer verder. Dat is 84 * een playlistgebaar. Op een cassette bestaat "volgend nummer" niet -- je houdt 85 * de knop ingedrukt, de band loopt door, en je laat los waar je bent. Robin 86 * wees daarop (21-8) en hij heeft gelijk: met knoppen die per nummer springen 87 * is het een lijst met een cassetteplaatje erboven. 88 * 89 * Het versnelt terwijl je hem vasthoudt, zoals een echt bandje op gang komt. 90 * Een korte TIK spoelt een klein stukje -- dat is er voor toetsenbord en 91 * schermlezer, want vasthouden is met een spatiebalk geen gebaar. 92 */ 93 const START_SNELHEID = 4; // maal de normale snelheid bij het indrukken 94 const MAX_SNELHEID = 16; 95 const VERSNELLING = 1.35; // per stap 96 const STAP_MS = 120; 97 const TIK_STAP_S = 5; // een losse klik 98 99 let winder = null; 100 101 function stopWinden(tape) { 102 if (winder) { clearInterval(winder.timer); winder = null; } 103 if (tape) tape.classList.remove('is-winding', 'is-winding-back'); 104 } 105 106 function startWinden(tape, richting) { 107 const p = speler(); 108 if (!p || huidigeIndex(tape) < 0) return; 109 stopWinden(tape); 110 let snelheid = START_SNELHEID; 111 tape.classList.add('is-winding'); 112 if (richting < 0) tape.classList.add('is-winding-back'); 113 const timer = setInterval(() => { 114 snelheid = Math.min(MAX_SNELHEID, snelheid * VERSNELLING); 115 p.seekBy(richting * snelheid * (STAP_MS / 1000)); 116 tekenBand(tape); 117 }, STAP_MS); 118 winder = { timer, tape }; 119 } 120 121 function opPointerDown(e) { 122 const knop = e.target.closest && e.target.closest('[data-tape-go]'); 123 if (!knop) return; 124 const tape = knop.closest('.post-tape'); 125 if (!tape) return; 126 startWinden(tape, knop.dataset.tapeGo === 'fwd' ? 1 : -1); 127 } 128 129 function opPointerUp() { 130 if (winder) stopWinden(winder.tape); 131 } 132 78 133 function opKlik(e) { 79 134 const tape = e.target.closest && e.target.closest('.post-tape'); … … 83 138 const spoel = e.target.closest('[data-tape-go]'); 84 139 if (spoel) { 85 if (!p) return; 86 // Spoelen kan alleen als DIT bandje loopt. Anders zou de knop de wachtrij 87 // van een ander blok verzetten, en dat is niet wat een spoelknop op deze 88 // cassette hoort te doen. 89 if (huidigeIndex(tape) < 0) return; 90 if (spoel.dataset.tapeGo === 'fwd') p.next(); else p.prev(); 91 setTimeout(tekenAlles, 60); 140 // Een tik spoelt een stukje. Vasthouden gaat via de pointer-afhandelaars 141 // hierboven; die hebben dan al gespoeld en deze klik doet er nog een klein 142 // beetje bovenop, wat niet stoort. 143 if (!p || huidigeIndex(tape) < 0) return; 144 p.seekBy(spoel.dataset.tapeGo === 'fwd' ? TIK_STAP_S : -TIK_STAP_S); 145 setTimeout(() => tekenBand(tape), 60); 92 146 return; 93 147 } … … 96 150 if (play && p) { 97 151 // Loopt dit bandje al, dan is deze knop een pauzeknop. De globale 98 // afhandelaar van audio-player.js zou hem anders opnieuw vanaf nummer een152 // afhandelaar van audio-player.js zou hem anders opnieuw vanaf het begin 99 153 // starten, want die kent alleen "speel deze wachtrij". 100 154 const i = huidigeIndex(tape); … … 106 160 } 107 161 // Staat het bandje stil, dan laten we de klik doorlopen: de speler pakt de 108 // data-attributen op en zet de wachtrijop.162 // data-attributen op en zet de band op. 109 163 } 110 164 } … … 117 171 // die in de leesweergave een keer de hele site heeft vastgezet. 118 172 if (tikker) { clearInterval(tikker); tikker = null; } 119 if (gebonden) { gebonden.removeEventListener('click', opKlik, true); gebonden = null; } 173 stopWinden(null); 174 if (gebonden) { 175 gebonden.removeEventListener('click', opKlik, true); 176 gebonden.removeEventListener('pointerdown', opPointerDown, true); 177 gebonden.removeEventListener('pointerup', opPointerUp, true); 178 gebonden.removeEventListener('pointercancel', opPointerUp, true); 179 gebonden = null; 180 } 120 181 if (!tapes.length) return; 121 182 … … 125 186 gebonden = document; 126 187 gebonden.addEventListener('click', opKlik, true); 188 gebonden.addEventListener('pointerdown', opPointerDown, true); 189 // Loslaten telt ook als je BUITEN de knop loslaat, anders blijft de band 190 // doorspoelen als je met je vinger wegglijdt. 191 gebonden.addEventListener('pointerup', opPointerUp, true); 192 gebonden.addEventListener('pointercancel', opPointerUp, true); 127 193 128 194 tikker = setInterval(tekenAlles, TIK_MS);
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)