Changeset 3866994 in Klonkt for test/ward-sky.test.js


Ignore:
Timestamp:
08/12/2026 10:00:38 PM (3 months ago)
Author:
Robin <roboburr@…>
Parents:
5b6f93b
Message:

Ward-PWA: echte pinch-to-zoom op de avatarhemel

De hemel deed zoom met het muiswiel, maar de belofte 'knijpen op een
telefoon' in de comment was nog niet waar: er stond alleen wielcode en
een ongebruikte pinch-variabele. Nu echt twee-vinger pinch.

Pointers in een Map: één vinger pant of tikt, twee vingers knijpen. De
schaal volgt de verhouding van de vingerafstand, en we zoomen ROND het
midden tussen de vingers, niet rond het canvas-midden. Dat is het
verschil tussen een kaart en beeld dat onder je weg schuift: het
wereldpunt onder je vingers blijft staan. Het wiel op desktop gebruikt
nu dezelfde weg, om de muis.

Zorgvuldig met de tik: pas een tik als er NOOIT twee vingers lagen en de
ene vinger nauwelijks bewoog. Anders opent het einde van een knijp per
ongeluk een gesprek. En bij het loslaten van de tweede vinger wordt de
afstand opnieuw geijkt, zodat de overgebleven vinger niet met een sprong
verder pant. touch-action:none stond al aan in berichtenstand, dus de
browser laat de pinch aan ons.

Changed files:
src/assets/js/ward-sky.js

  • _zoomAround(px,py,factor): zoom om een schermpunt
  • _clampScale: de grenzen op één plek
  • _wire herschreven: multi-pointer pan/pinch/tik

test/ward-sky.test.js

  • zoomen houdt het punt onder je vingers op zijn plek; de zoom blijft binnen zijn grenzen

remarks: 908 tests groen. De rekenkant is getest; het gebaar zelf met
twee echte vingers is aan Robin op dev.

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • test/ward-sky.test.js

    r5b6f93b r3866994  
    99import assert from 'node:assert/strict';
    1010
    11 const { orbitPlacement, nearestFace } = await import('../src/assets/js/ward-sky.js');
     11const { orbitPlacement, nearestFace, SkyRenderer } = await import('../src/assets/js/ward-sky.js');
    1212
    1313const r = (s) => Math.hypot(s.x, s.y);
    … …  
    6868  assert.equal(at(1.5), 1);
    6969});
     70
     71test('zoomen houdt het punt onder je vingers op zijn plek', () => {
     72  // De kern van pinch-to-zoom: de wereld onder het midden tussen je vingers
     73  // mag NIET wegschuiven. We rekenen _zoomAround na zonder een echt canvas,
     74  // door de renderer een minimale staat te geven.
     75  // We hebben geen DOM, dus bouwen een kaal object met alleen wat _zoomAround
     76  // aanraakt en lenen de methode.
     77  const fake = { w: 400, h: 400, scale: 1, panX: 0, panY: 0,
     78    _clampScale: SkyRenderer.prototype._clampScale };
     79  const zoom = SkyRenderer.prototype._zoomAround;
     80
     81  // Welk wereldpunt ligt nu onder (px,py)?
     82  const worldUnder = (o, px, py) => ({
     83    x: (px - o.w / 2 - o.panX) / o.scale,
     84    y: (py - o.h / 2 - o.panY) / o.scale,
     85  });
     86  const px = 300, py = 120;
     87  const before = worldUnder(fake, px, py);
     88  zoom.call(fake, px, py, 1.6);   // inzoomen om dat punt
     89  const after = worldUnder(fake, px, py);
     90
     91  assert.ok(Math.abs(before.x - after.x) < 1e-6, 'x schoof weg onder de vingers');
     92  assert.ok(Math.abs(before.y - after.y) < 1e-6, 'y schoof weg onder de vingers');
     93  assert.ok(fake.scale > 1, 'er is niet ingezoomd');
     94});
     95
     96test('de zoom blijft binnen zijn grenzen', () => {
     97  const clamp = SkyRenderer.prototype._clampScale;
     98  assert.equal(clamp(10), 2.5);    // niet eindeloos in
     99  assert.equal(clamp(0.01), 0.2);  // niet eindeloos uit
     100});
Note: See TracChangeset for help on using the changeset viewer.