@johnmorrisdotca/kyogijo-stadiums 0.56.0 → 0.57.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -7,6 +7,13 @@ All notable changes to this project are written here. The format follows
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.57.0] - 2026-11-03
11
+
12
+ ### Changed
13
+
14
+ - **The wheel zooms the 3D view** (KAZOKU-UI-45). The wheel over the view now zooms it, as a map does (up in, down out, about the view's middle, which is where the pinch and the buttons zoom; a notch about as much as the + key); before, the plain wheel was the page's and tipped a focused view. A trackpad's pinch (Ctrl or Command and the wheel) still zooms. Shift and the wheel, or a sideways swipe, turns the view. The wheel never tips it: a drag, the arrows and the buttons do. With the pointer anywhere else the wheel scrolls the page, and a wheel that starts while the zoom is already at its end that way scrolls the page too, so a page of views is never trapped; the steps of a turn that reaches the end part-way through stay with the view, so the page does not jump.
15
+
16
+
10
17
  ## [0.56.0] - 2026-11-03
11
18
 
12
19
  ### Added
package/catalogue.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "generatedAt": "2026-11-03",
4
4
  "package": {
5
5
  "name": "@johnmorrisdotca/kyogijo-stadiums",
6
- "version": "0.56.0"
6
+ "version": "0.57.0"
7
7
  },
8
8
  "address": "https://johnmorrisdotca.github.io/kyogijo-stadiums/catalogue.json",
9
9
  "site": "https://johnmorrisdotca.github.io/kyogijo-stadiums/",
@@ -3,7 +3,7 @@ export const CATALOGUE_DATA = {
3
3
  "generatedAt": "2026-11-03",
4
4
  "package": {
5
5
  "name": "@johnmorrisdotca/kyogijo-stadiums",
6
- "version": "0.56.0"
6
+ "version": "0.57.0"
7
7
  },
8
8
  "address": "https://johnmorrisdotca.github.io/kyogijo-stadiums/catalogue.json",
9
9
  "site": "https://johnmorrisdotca.github.io/kyogijo-stadiums/",
@@ -78,11 +78,14 @@ export declare function nudge(view: TurnView, toward: TurnToward, amount: number
78
78
  * yaw falls) and a drag down tips the top toward the eye (the pitch falls).
79
79
  */
80
80
  export declare function drag(view: TurnView, dx: number, dy: number, tilt?: boolean, degreesPerPixel?: number): TurnView;
81
+ /** Wheel steps closer together than this, in milliseconds, are one turn of the wheel or one swipe (with its glide). */
82
+ export declare const WHEEL_GESTURE_MS = 300;
81
83
  /**
82
- * The view after the wheel turns by `deltaY` (positive is down, as `WheelEvent.deltaY` says) while the view has focus: the wheel up tips the surface as a drag up does (the near edge goes up, the
83
- * front is lifted: the pitch rises) and the wheel down as a drag down does.
84
+ * The view after the wheel turns by `deltaY` (positive is down, as `WheelEvent.deltaY` says; `deltaMode` 1 is lines and 2 is pages): the wheel up zooms in and the wheel down zooms out,
85
+ * about the view's middle, as the pinch and the buttons do (the view has no pan). A trackpad's pinch (`pinch`: it arrives as Ctrl and the wheel) comes in small steps; a plain wheel's
86
+ * notch is about 100 pixels and zooms about 1.2 times, as the + key does, and one step of it never zooms more than twice either way.
84
87
  */
85
- export declare const wheelTip: (view: TurnView, deltaY: number) => TurnView;
88
+ export declare function wheelZoom(view: TurnView, deltaY: number, deltaMode?: number, pinch?: boolean): TurnView;
86
89
  /** A box in the scene, in pixels from the scene's middle, the floor at `z0` and the highest thing at `z1`. */
87
90
  export interface Box3 {
88
91
  x0: number;
@@ -100,11 +100,18 @@ export function nudge(view, toward, amount) {
100
100
  export function drag(view, dx, dy, tilt = true, degreesPerPixel = 0.4) {
101
101
  return clampView({ ...view, yaw: view.yaw - dx * degreesPerPixel, pitch: tilt ? view.pitch - dy * degreesPerPixel * 0.75 : view.pitch });
102
102
  }
103
+ /** Wheel steps closer together than this, in milliseconds, are one turn of the wheel or one swipe (with its glide). */
104
+ export const WHEEL_GESTURE_MS = 300;
103
105
  /**
104
- * The view after the wheel turns by `deltaY` (positive is down, as `WheelEvent.deltaY` says) while the view has focus: the wheel up tips the surface as a drag up does (the near edge goes up, the
105
- * front is lifted: the pitch rises) and the wheel down as a drag down does.
106
+ * The view after the wheel turns by `deltaY` (positive is down, as `WheelEvent.deltaY` says; `deltaMode` 1 is lines and 2 is pages): the wheel up zooms in and the wheel down zooms out,
107
+ * about the view's middle, as the pinch and the buttons do (the view has no pan). A trackpad's pinch (`pinch`: it arrives as Ctrl and the wheel) comes in small steps; a plain wheel's
108
+ * notch is about 100 pixels and zooms about 1.2 times, as the + key does, and one step of it never zooms more than twice either way.
106
109
  */
107
- export const wheelTip = (view, deltaY) => clampView({ ...view, pitch: view.pitch - deltaY * 0.15 });
110
+ export function wheelZoom(view, deltaY, deltaMode = 0, pinch = false) {
111
+ const pixels = deltaMode === 1 ? deltaY * (pinch ? 5 : 33) : deltaMode === 2 ? deltaY * 800 : deltaY;
112
+ const factor = pinch ? Math.exp(clamp(-pixels * 0.01, -10, 10)) : clamp(Math.exp(-pixels * 0.002), 0.5, 2);
113
+ return clampView({ ...view, zoom: view.zoom * factor });
114
+ }
108
115
  const RAD = Math.PI / 180;
109
116
  /** Where a point of the scene falls on the screen, in pixels from the middle of the container, when the scene is placed as given and the eye is `distance` pixels away. */
110
117
  export function project(point, view, at, distance) {
package/dist/turn.dom.js CHANGED
@@ -1,10 +1,10 @@
1
1
  // The 3D view in a page: `mountKyogijoTurn` writes the scene (`turn.markup.ts`) into a container and makes it turn, as the cube of kyuubu turns: a drag turns and
2
- // tips it, a pinch or Ctrl and the wheel zoom, the arrow keys step it, four viewpoints and a reset are a button or a number key away, a reader who prefers
2
+ // tips it, the wheel or a pinch zooms, the arrow keys step it, four viewpoints and a reset are a button or a number key away, a reader who prefers
3
3
  // reduced motion gets jumps for glides, and where the browser cannot draw in 3D the flat drawing stays. Nothing is polled and nothing runs while the view is
4
4
  // still: the elements' `transform`s are written when the view changes, and a glide between viewpoints is a short run of animation frames.
5
5
  import { displayProbe, frameBatch } from "./turn.frames.js";
6
6
  import { drawKyogijo } from "./draw.js";
7
- import { STEP, TURN_PRESET_NAMES, clampView, drag, nearest, nudge, presetOf, presetView, step, turnDirection, viewScale, wheelTip } from "./turn.camera.js";
7
+ import { STEP, TURN_PRESET_NAMES, clampView, drag, nearest, nudge, presetOf, presetView, step, turnDirection, viewScale, wheelZoom, WHEEL_GESTURE_MS, ZOOM_MAX, ZOOM_MIN } from "./turn.camera.js";
8
8
  import { buildTurn, floorOptions, openingView, turnWords } from "./turn.model.js";
9
9
  import { controlsMarkup, layoutOf, turnMarkupOf, worldMarkup } from "./turn.markup.js";
10
10
  import { KYOGIJO_TURN_STYLE } from "./turn.style.js";
@@ -656,20 +656,33 @@ export function mountTurn(host, options, settings, build, replayable = false, le
656
656
  stage.addEventListener("pointerup", onUp);
657
657
  stage.addEventListener("pointercancel", onUp);
658
658
  stage.addEventListener("dblclick", toOpening);
659
- // ---- The wheel: Ctrl and the wheel (a pinch on a trackpad) zoom; with the view focused the wheel tips and turns it; otherwise the page scrolls as ever. ----
659
+ // ---- The wheel over the view zooms it, as a map does; with the pointer anywhere else the page scrolls. Ctrl or Command and the wheel (a pinch on a trackpad) zoom too. Shift and the
660
+ // wheel, or a sideways swipe, turn it. Tipping is a drag, the keys and the buttons. A wheel that starts while the zoom is already at its end that way goes on to scroll the page, so the page is
661
+ // never trapped; one that reaches the end part-way through stops there rather than flinging the page. ----
662
+ let wheelTaken = Number.NEGATIVE_INFINITY;
660
663
  const onWheel = (event) => {
661
- if (event.ctrlKey) {
664
+ const pinch = event.ctrlKey || event.metaKey;
665
+ const now = Number.isFinite(event.timeStamp) ? event.timeStamp : 0;
666
+ const continuing = now >= wheelTaken && now - wheelTaken < WHEEL_GESTURE_MS;
667
+ if (!pinch && (event.shiftKey || Math.abs(event.deltaX) > Math.abs(event.deltaY))) {
662
668
  event.preventDefault();
669
+ wheelTaken = now;
663
670
  grab();
664
- view = clampView({ ...view, zoom: view.zoom * Math.exp(-event.deltaY * 0.01) });
671
+ view = clampView({ ...view, yaw: view.yaw + (event.deltaX || event.deltaY) * 0.25 });
665
672
  }
666
- else if (doc.activeElement === stage) {
673
+ else {
674
+ const next = wheelZoom(view, event.deltaY, event.deltaMode, pinch);
675
+ const atEnd = event.deltaY <= 0 ? view.zoom >= ZOOM_MAX : view.zoom <= ZOOM_MIN;
676
+ // Ctrl and the wheel is always the view's, or the browser would zoom the whole page.
677
+ if (!pinch && atEnd && !continuing)
678
+ return;
667
679
  event.preventDefault();
680
+ wheelTaken = now;
681
+ if (next.zoom === view.zoom)
682
+ return;
668
683
  grab();
669
- view = event.shiftKey || Math.abs(event.deltaX) > Math.abs(event.deltaY) ? clampView({ ...view, yaw: view.yaw + (event.deltaX || event.deltaY) * 0.25 }) : wheelTip(view, event.deltaY);
684
+ view = next;
670
685
  }
671
- else
672
- return;
673
686
  shown = view;
674
687
  paint(shown);
675
688
  label();
package/dist/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  /** The package's version: the same as package.json's, and a test holds them to each other. */
2
- export declare const VERSION = "0.56.0";
2
+ export declare const VERSION = "0.57.0";
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /** The package's version: the same as package.json's, and a test holds them to each other. */
2
- export const VERSION = "0.56.0";
2
+ export const VERSION = "0.57.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@johnmorrisdotca/kyogijo-stadiums",
3
- "version": "0.56.0",
3
+ "version": "0.57.0",
4
4
  "description": "Kyogijo Stadiums 競技場, 40 sports' surfaces as SVG, drawn to scale from the rulebooks: NFL, CFL and IFAF football fields, an NHL rink, an NBA court, MLB ballparks, soccer pitches, curling sheets, athletics stadiums, speed skating, short track and figure skating rinks, swimming pools, water polo fields, diving wells, artistic swimming areas, and the courts and fields of tennis, volleyball (indoor, beach and sitting), badminton, pickleball, table tennis, padel, squash, racquetball, sepak takraw, teqball, roundnet, netball, lacrosse, rugby, Australian football, Gaelic games, cricket, field hockey and handball, and the budo of judo, karate, kendo, sumo and kyudo with a dojo of tatami laid as real units, the MMA cage, with each team's name and logo on its side and the score in the middle, stands and a crowd, a pageant of flags, and a 3D view. Light and dark, accessible, a compact badge for lists, a helper for React and a custom element. Zero dependencies.",
5
5
  "keywords": [
6
6
  "sports",