Changeset e679bce in Klonkt for src/assets/css/style.css


Ignore:
Timestamp:
08/22/2026 09:54:51 AM (3 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
8bb3b09
Parents:
16fd4fe
Message:

Het bandje speelt als bandje: een cassette, een object, spoelen in seconden

Robins correctie (21-8): vooruit en achteruit deden hier next()/prev(), en dat
is een playlistgebaar. Dan is het een lijst met een cassetteplaatje erboven.
Een cassette kent geen "volgend nummer" -- je houdt de knop ingedrukt, de band
loopt door, en je laat los waar je bent.

Dat kan omdat audio-player.js een wachtrij al in EEN doorlopende
MediaSource-tijdlijn giet: "een trackwissel is een positie, geen omschakeling".
Een bandje IS die tijdlijn. Dus:

  • seekBy(seconden) op de speler, over de nummergrenzen heen. Op de blob-motor (iOS, geen MSE) bestaat die tijdlijn niet; daar loopt spoelen tot de rand van het nummer en stapt dan naar de buur. Grover, maar eerlijker dan doen alsof.
  • Bandmodus: de speler toont het BANDJE als titel met het lopende nummer eronder, en de teller loopt over de hele band in plaats van per nummer. Dat is wat "een object, geen losse tracks" betekent op het scherm.
  • Vasthouden versnelt (4x tot 16x), loslaten stopt -- ook als je buiten de knop loslaat. Een korte tik spoelt vijf seconden, want vasthouden is met een spatiebalk geen gebaar.

Een echte cassette, als SVG. Verhouding 100,4 x 63,8 mm, de maat van een
compact cassette, dus viewBox 314x200: behuizing, labelvlak met de titel erop,
venster, twee spoelen met tandjes die meedraaien, de bandpakketten, vier
schroefjes en de openingen voor de kop en de capstans. De vorige versie waren
twee CSS-schijfjes.

Twee dingen die alleen door het echt te draaien boven kwamen:

  • audio-player.js kiest zijn knoppen met een lijst KLASSENAMEN (PLAY_SELECTOR), niet met een regel over data-attributen. De cassetteknop droeg alle juiste data-pcms-* en deed niets. Er staat nu een test op.
  • De sessie sloeg displayTimes().cur op als trackpositie. In bandmodus is dat de bandteller, dus een hersteld bandje sprong naar een plek die in dat nummer niet bestaat. Daarvoor is trackTijd() afgesplitst.

MOD_V 53, style.css v107, audio-player v35.

Co-Authored-By: Claude Opus 5 <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/assets/css/style.css

    r16fd4fe re679bce  
    50785078
    50795079/* ── Het bandje (mixtape) ──────────────────────────────────────────────
    5080    Zelfde familie als .post-album hierboven: dezelfde rand, dezelfde radius,
    5081    dezelfde papierkleur. Het verschil zit in wat je ziet draaien, niet in een
    5082    ander jasje -- een mixtape is een soort uitgave binnen Klonkt, geen ander
    5083    product.
    5084 
    5085    Alles hieronder gebruikt de bestaande variabelen (--rule, --paper-2, --ink,
    5086    --accent), dus het volgt licht en donker en het accent van de site vanzelf. */
     5080   Een cassette, getekend als SVG op de echte maat: 100,4 x 63,8 mm, dus een
     5081   viewBox van 314x200. De vorige versie tekende twee schijfjes met CSS; dit is
     5082   een replica -- behuizing, labelvlak, venster, twee spoelen met tandjes, de
     5083   schroefjes in de hoeken en de openingen voor de kop en de capstans onderin.
     5084
     5085   Alle kleuren komen uit de bestaande variabelen, dus licht, donker en het
     5086   accent van de site volgen vanzelf. */
    50875087.post-tape {
    50885088    position: relative;
     
    50945094}
    50955095
    5096 /* De cassette zelf. De verhouding is die van een echt bandje (ongeveer 10:6),
    5097    zodat hij ook op een telefoon als cassette leest en niet als balk. */
    5098 .tape-shell {
    5099     display: grid;
    5100     grid-template-rows: auto auto;
    5101     gap: .5rem;
    5102     padding: .8rem .8rem .4rem;
    5103 }
    5104 .tape-window {
    5105     position: relative;
    5106     display: flex;
    5107     align-items: center;
    5108     justify-content: center;
    5109     gap: 12%;
    5110     padding: .9rem 1.2rem;
    5111     border-radius: 10px;
    5112     background: color-mix(in srgb, var(--ink) 8%, transparent);
    5113     border: 1px solid var(--rule, rgba(0,0,0,.12));
    5114 }
    5115 /* De band tussen de spoelen. Een dun lijntje is genoeg: het gaat om de twee
    5116    draaiende schijven, dat is wat een cassette een cassette maakt. */
    5117 .tape-band {
     5096.tape-shell { position: relative; padding: .8rem .8rem .3rem; }
     5097.tape-svg { display: block; width: 100%; height: auto; }
     5098
     5099/* De behuizing. Twee lagen zodat er een randje omheen zit, zoals bij een echt
     5100   doosje waar de bovenschaal iets uitsteekt. */
     5101.tape-body { fill: color-mix(in srgb, var(--ink) 82%, var(--paper, #fff)); }
     5102.tape-body-inner { fill: color-mix(in srgb, var(--ink) 70%, var(--paper, #fff)); }
     5103.tape-labelplate { fill: color-mix(in srgb, var(--paper, #fff) 92%, var(--accent)); }
     5104.tape-glass {
     5105    fill: color-mix(in srgb, var(--ink) 88%, transparent);
     5106    stroke: color-mix(in srgb, var(--paper, #fff) 25%, transparent);
     5107    stroke-width: 1.5;
     5108}
     5109.tape-pack { fill: color-mix(in srgb, var(--ink) 55%, var(--paper, #fff)); }
     5110.tape-ribbon { fill: color-mix(in srgb, var(--ink) 45%, var(--paper, #fff)); }
     5111.tape-hub { fill: var(--paper, #fff); }
     5112.tape-tooth { fill: color-mix(in srgb, var(--ink) 60%, var(--paper, #fff)); }
     5113.tape-screw { fill: color-mix(in srgb, var(--ink) 55%, var(--paper, #fff)); }
     5114.tape-slot { fill: color-mix(in srgb, var(--ink) 92%, transparent); }
     5115.tape-slot--capstan { fill: color-mix(in srgb, var(--ink) 96%, transparent); }
     5116
     5117/* Draaien. De tandjes zitten in dezelfde groep als de naaf, dus de hele spoel
     5118   draait als een geheel -- daar gaat het om, want aan die tandjes zie je pas
     5119   DAT hij draait. Het label blijft stil, anders wordt de titel onleesbaar. */
     5120.post-tape.is-playing .tape-reel { animation: tape-spin 3s linear infinite; }
     5121.post-tape.is-playing .tape-reel--right { animation-duration: 2.2s; }
     5122/* Spoelen: veel sneller, en achteruit ook echt achteruit. */
     5123.post-tape.is-winding .tape-reel { animation-duration: .45s; }
     5124.post-tape.is-winding-back .tape-reel { animation-direction: reverse; }
     5125@keyframes tape-spin { to { transform: rotate(360deg); } }
     5126@media (prefers-reduced-motion: reduce) {
     5127    .post-tape.is-playing .tape-reel,
     5128    .post-tape.is-winding .tape-reel { animation: none; }
     5129}
     5130
     5131/* De tekst staat OP het labelvlak van de cassette. Percentages volgen de
     5132   viewBox, dus het blijft kloppen op elke breedte. */
     5133.tape-label {
    51185134    position: absolute;
    5119     left: 22%; right: 22%;
    5120     height: 3px;
    5121     background: color-mix(in srgb, var(--ink) 35%, transparent);
    5122     border-radius: 2px;
    5123 }
    5124 .tape-reel {
    5125     position: relative;
    5126     width: clamp(48px, 16vw, 76px);
    5127     aspect-ratio: 1;
    5128     border-radius: 50%;
    5129     background:
    5130       repeating-conic-gradient(from 0deg,
    5131         color-mix(in srgb, var(--ink) 22%, transparent) 0deg 12deg,
    5132         transparent 12deg 24deg);
    5133     border: 2px solid color-mix(in srgb, var(--ink) 30%, transparent);
    5134     display: grid;
    5135     place-items: center;
    5136 }
    5137 .tape-reel-hub {
    5138     width: 34%;
    5139     aspect-ratio: 1;
    5140     border-radius: 50%;
    5141     background: var(--paper, #fff);
    5142     border: 2px solid color-mix(in srgb, var(--ink) 40%, transparent);
    5143 }
    5144 /* Draaien doet hij alleen als hij speelt. De animatie staat op de spoel en niet
    5145    op de hele cassette: het label hoort stil te blijven, anders wordt de titel
    5146    onleesbaar. */
    5147 .post-tape.is-playing .tape-reel { animation: tape-spin 2.4s linear infinite; }
    5148 .post-tape.is-playing .tape-reel--right { animation-duration: 3.2s; }
    5149 @keyframes tape-spin { to { transform: rotate(360deg); } }
    5150 /* Wie liever geen beweging ziet, krijgt geen beweging. De cassette blijft dan
    5151    gewoon staan; de statusregel eronder vertelt nog steeds wat er speelt. */
    5152 @media (prefers-reduced-motion: reduce) {
    5153     .post-tape.is-playing .tape-reel { animation: none; }
    5154 }
    5155 
    5156 .tape-label {
    5157     padding: .5rem .6rem;
    5158     border-radius: 8px;
    5159     background-size: cover;
    5160     background-position: center;
    5161     position: relative;
    5162 }
    5163 /* Staat er een hoes achter het label, dan moet de tekst leesbaar blijven. */
    5164 .tape-label[style] { color: #fff; text-shadow: 0 1px 3px rgba(0,0,0,.7); }
     5135    left: 8.4%; right: 8.4%;
     5136    top: calc(.8rem + 11%);
     5137    height: 31%;
     5138    padding: .1rem .4rem;
     5139    color: color-mix(in srgb, var(--ink) 92%, transparent);
     5140    overflow: hidden;
     5141}
    51655142.tape-kind {
    51665143    margin: 0;
    5167     font-size: .7rem;
    5168     letter-spacing: .06em;
     5144    font-size: clamp(.55rem, 1.6vw, .68rem);
     5145    letter-spacing: .14em;
    51695146    text-transform: uppercase;
    5170     opacity: .75;
    5171 }
    5172 .tape-title { margin: .1rem 0 0; font-size: 1.05rem; line-height: 1.25; }
    5173 .tape-artist { margin: .05rem 0 0; font-size: .85rem; opacity: .8; }
    5174 .tape-meta { margin: .15rem 0 0; font-size: .75rem; opacity: .65; }
    5175 
    5176 /* De knoppen: terugspoelen, spelen, vooruitspoelen. Meer heeft een bandje niet,
    5177    en dat is de bedoeling -- er is geen zoekbalk omdat je op een cassette niet
    5178    kunt zoeken. */
     5147    opacity: .7;
     5148}
     5149.tape-title {
     5150    margin: 0;
     5151    font-size: clamp(.85rem, 2.6vw, 1.1rem);
     5152    line-height: 1.15;
     5153    white-space: nowrap;
     5154    overflow: hidden;
     5155    text-overflow: ellipsis;
     5156}
     5157.tape-artist { margin: 0; font-size: clamp(.65rem, 1.9vw, .8rem); opacity: .8; }
     5158.tape-meta { margin: 0; font-size: clamp(.6rem, 1.7vw, .72rem); opacity: .6; }
     5159
     5160/* De knoppen: terugspoelen, spelen, vooruitspoelen. Meer heeft een cassette
     5161   niet, en dat is de bedoeling -- er is geen zoekbalk omdat je op een bandje
     5162   niet kunt zoeken, alleen spoelen. */
    51795163.tape-controls {
    51805164    display: flex;
     
    51825166    justify-content: center;
    51835167    gap: .6rem;
    5184     padding: .3rem 0 .7rem;
     5168    padding: .5rem 0 .6rem;
    51855169}
    51865170.tape-btn {
     
    51945178    cursor: pointer;
    51955179    padding: 0;
     5180    touch-action: manipulation;   /* vasthouden mag geen zoom of scroll worden */
     5181    user-select: none;
    51965182}
    51975183.tape-btn svg { width: 18px; height: 18px; }
     
    52055191}
    52065192.tape-btn--play svg { width: 22px; height: 22px; }
    5207 /* Speelt hij, dan is dezelfde knop de pauzeknop. Twee knoppen zou een bandje
    5208    niet hebben. */
    5209 .post-tape.is-playing .tape-btn--play svg path { d: path("M7 5h4v14H7zM13 5h4v14h-4z"); }
     5193.post-tape.is-winding .tape-btn--back,
     5194.post-tape.is-winding .tape-btn--fwd { border-color: var(--accent); color: var(--accent); }
    52105195
    52115196.tape-now {
Note: See TracChangeset for help on using the changeset viewer.