@a2f0/skyline 0.2.63 → 0.2.64

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/README.md CHANGED
@@ -23,7 +23,7 @@ Serve `dist/` over HTTP rather than opening files directly: WebGL and the 3D pag
23
23
 
24
24
  | Page | Shows | Docs |
25
25
  | --- | --- | --- |
26
- | `index.html` | The viewer, mounted as the package mounts it: opens on the 3D skyline, with the enhanced drawing, the original drawing, and a WebGL prototype one button away | [The viewer](docs/viewer.md) |
26
+ | `index.html` | The viewer, mounted as the package mounts it: opens on the 3D skyline, with the original drawing one button away and links to the enhanced drawing and the WebGL prototype | [The viewer](docs/viewer.md) |
27
27
  | `skyline-3d.html` | The full-screen 3D skyline on its own: camera views, streets, footprints, celebratory lights, and a building menu | [Full-screen 3D skyline](docs/viewer.md#full-screen-3d-skyline) |
28
28
  | `building-detail.html?building=<id>` | One mapped building alone on its platform | [Building menu and detail](docs/viewer.md#building-menu-and-detail) |
29
29
  | `skyline-study.html` | The 3D scene over the drawing, in the geographic layout or the original drawing's fit | [3D studies](docs/studies.md#skyline-study) |
package/docs/package.md CHANGED
@@ -312,8 +312,8 @@ Before 0.2, the viewer ran in an iframe. Hosts upgrading:
312
312
  - If the viewer's or scene's code fails to load, as on a dropped connection, the
313
313
  browser keeps that failure for the page: later mounts on the same page fail the same
314
314
  way until it reloads. A frame used to retry with a new document.
315
- - The site's own `index.html` shows two prototypes from its toolbar, the hover-scripted
316
- enhanced drawing and the WebGL prototype, as pages of their own in frames; a host's
315
+ - The site's own `index.html` links two prototypes from its toolbar, the hover-scripted
316
+ enhanced drawing and the WebGL prototype, which open as pages of their own; a host's
317
317
  viewer never shows them.
318
318
 
319
319
  ## Import a scene or a building
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@a2f0/skyline",
3
- "version": "0.2.63",
3
+ "version": "0.2.64",
4
4
  "description": "Interactive Chicago skyline viewer and reusable Three.js building models",
5
5
  "license": "UNLICENSED",
6
6
  "repository": {
@@ -5,9 +5,6 @@
5
5
  preserveAspectRatio="xMidYMax meet"
6
6
  version="1.1"
7
7
  id="svg6766"
8
- role="img"
9
- aria-label="Chicago skyline at night"
10
- aria-describedby="skyline-description"
11
8
  style="color-scheme:dark"
12
9
  sodipodi:docname="skyline-animated.svg"
13
10
  inkscape:version="1.1 (c4e8f9e, 2021-05-24)"
@@ -144,12 +141,22 @@
144
141
  .building-tooltip {
145
142
  pointer-events: none;
146
143
  }
144
+ .back-link text {
145
+ fill: #a8a8a8;
146
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
147
+ text-decoration: underline;
148
+ }
149
+ .back-link:hover text,
150
+ .back-link:focus-visible text {
151
+ fill: #ffffff;
152
+ }
147
153
  @media (prefers-reduced-motion: reduce) {
148
154
  .interactive-building.is-active { transition: none; }
149
155
  }
150
156
  ]]></style>
151
157
  </defs>
152
- <g id="skyline-position" transform="translate(1105.5923,-87.26366)">
158
+ <!-- The drawing is one image; the root stays a plain document so the link back reaches assistive technology. -->
159
+ <g id="skyline-position" transform="translate(1105.5923,-87.26366)" role="img" aria-label="Chicago skyline at night" aria-describedby="skyline-description">
153
160
  <g
154
161
  inkscape:groupmode="layer"
155
162
  id="layer4"
@@ -18670,6 +18677,17 @@
18670
18677
  style="display:inline;stroke-width:1.33526" />
18671
18678
  </g>
18672
18679
  </g>
18680
+ <!-- Opened on its own, the drawing links back to the viewer; the script keeps it in the top-left corner. -->
18681
+ <a
18682
+ id="back-link"
18683
+ class="back-link"
18684
+ href="index.html">
18685
+ <text
18686
+ id="back-link-text"
18687
+ font-size="70"
18688
+ x="40"
18689
+ y="110">← back to skyline</text>
18690
+ </a>
18673
18691
  <g
18674
18692
  id="building-tooltip"
18675
18693
  class="building-tooltip"
@@ -18788,6 +18806,21 @@
18788
18806
  }
18789
18807
  }
18790
18808
 
18809
+ // The way back to the viewer: 12px text, 12px in from the window's top left, at every
18810
+ // window size.
18811
+ const backLink = document.querySelector("#back-link-text");
18812
+ function placeBackLink() {
18813
+ const matrix = svg.getScreenCTM();
18814
+ if (!matrix) return;
18815
+ const scale = Math.hypot(matrix.a, matrix.b) || 1;
18816
+ const start = svgPoint(0, 0, matrix.inverse());
18817
+ backLink.setAttribute("font-size", 12 / scale);
18818
+ backLink.setAttribute("x", start.x + 12 / scale);
18819
+ backLink.setAttribute("y", start.y + 24 / scale);
18820
+ }
18821
+ placeBackLink();
18822
+ window.addEventListener("resize", placeBackLink, { passive: true });
18823
+
18791
18824
  svg.addEventListener("pointerover", updateHover, { passive: true });
18792
18825
  svg.addEventListener("pointermove", updateHover, { passive: true });
18793
18826
  svg.addEventListener("pointerleave", deactivate);
@@ -1,20 +1,18 @@
1
1
  import { loadMarkup } from "./markup.js";
2
2
  import { provideThree } from "./three-engine.js";
3
- // What each of the site toolbar's mode buttons shows, says and announces. The viewer opens
4
- // on the 3D skyline; each toggle shows its mode and, pressed again, returns to it.
3
+ // What the site toolbar's mode button shows, says and announces. The viewer opens on the 3D
4
+ // skyline; the toggle shows the original drawing and, pressed again, returns to it.
5
5
  const home = { label: "3d skyline", title: "Return to the 3D skyline", status: "3D skyline displayed" };
6
6
  const toggles = {
7
7
  original: { id: "toggle-skyline", label: "show original", title: "Compare with the original skyline SVG", status: "Original skyline displayed" },
8
- webgl: { id: "toggle-webgl", label: "show webgl", title: "Preview the WebGL skyline prototype", status: "WebGL skyline prototype displayed" },
9
- enhanced: { id: "toggle-enhanced", label: "show enhanced", title: "Show the enhanced interactive skyline drawing", status: "Enhanced interactive skyline displayed" },
10
- };
11
- // The two prototypes the site's toolbar shows in place are pages of their own, as the
12
- // studies are: the hover-scripted drawing and the WebGL prototype. Only the site's own
13
- // index.html shows them, in frames; a host's viewer never does.
14
- const prototypes = {
15
- enhanced: { src: "skyline-animated.svg", title: "Animated Chicago skyline at night" },
16
- webgl: { src: "skyline-webgl.html", title: "WebGL Chicago skyline prototype" },
17
8
  };
9
+ // The two prototypes are pages of their own, as the studies are: the hover-scripted drawing
10
+ // and the WebGL prototype. The site's toolbar links to them, and each page keeps its own
11
+ // scripts and a way back; a host's viewer never shows them.
12
+ const prototypes = [
13
+ { id: "link-webgl", href: "skyline-webgl.html", label: "webgl prototype", title: "Open the WebGL skyline prototype", ct: "viewer.webgl" },
14
+ { id: "link-enhanced", href: "skyline-animated.svg", label: "enhanced drawing", title: "Open the enhanced interactive skyline drawing", ct: "viewer.enhanced" },
15
+ ];
18
16
  export function sceneTransition(status, event) {
19
17
  switch (event) {
20
18
  case "ready":
@@ -66,7 +64,6 @@ export function mount(root, { assets, signal, controls, colour, theme, attributi
66
64
  // Both show original buttons wait while the scene boots, until its first frame, a failure
67
65
  // to load, or a lost graphics context; the drawing stays reachable while it is unavailable.
68
66
  let sceneStatus = "booting";
69
- const frames = {};
70
67
  const toolbar = navigation ? createToolbar() : null;
71
68
  function updateView() {
72
69
  viewer.toggleAttribute("data-booting", sceneStatus !== "ready" && mode === "3d");
@@ -74,10 +71,6 @@ export function mount(root, { assets, signal, controls, colour, theme, attributi
74
71
  if (mode === "original" && !drawing.getAttribute("src"))
75
72
  drawing.src = new URL("skyline-original-fit.svg", assets).href;
76
73
  drawing.hidden = mode !== "original";
77
- if (mode === "enhanced" || mode === "webgl")
78
- frames[mode] ??= createPrototype(mode);
79
- for (const [name, frame] of Object.entries(frames))
80
- frame.hidden = name !== mode;
81
74
  originalReturn.hidden = mode !== "original";
82
75
  embeddedOriginal.hidden = navigation || mode !== "3d" || sceneStatus !== "unavailable";
83
76
  if (toolbar) {
@@ -295,6 +288,9 @@ export function mount(root, { assets, signal, controls, colour, theme, attributi
295
288
  toggleButton.addEventListener("click", () => showMode(mode === name ? "3d" : name), listening);
296
289
  nav.append(toggleButton);
297
290
  }
291
+ for (const prototype of prototypes) {
292
+ nav.append(element(document, "a", { id: prototype.id, href: new URL(prototype.href, assets).href, title: prototype.title, textContent: prototype.label }, { "data-ct": prototype.ct }));
293
+ }
298
294
  nav.append(element(document, "a", { href: new URL("building-study.html", assets).href, textContent: "3d building" }, { "data-ct": "viewer.building-study" }), element(document, "a", { href: new URL("skyline-study.html", assets).href, textContent: "skyline study" }, { "data-ct": "viewer.skyline-study" }));
299
295
  const debugButton = button("debug-motion", "debug motion", { "aria-describedby": "stars-motion-status" });
300
296
  const motionStatus = element(document, "p", { className: "motion-status", id: "stars-motion-status" }, { role: "status" });
@@ -329,17 +325,4 @@ export function mount(root, { assets, signal, controls, colour, theme, attributi
329
325
  resizing.observe(scene);
330
326
  signal.addEventListener("abort", () => resizing.disconnect(), { once: true });
331
327
  }
332
- // A prototype's page, in a frame of its own, shown in place the first time it is chosen.
333
- // Keys pressed inside it go to its own window, so F listens there too.
334
- function createPrototype(name) {
335
- const frame = element(document, "iframe", { className: "scene", id: `${name}-scene`, title: prototypes[name].title, src: new URL(prototypes[name].src, assets).href });
336
- frame.addEventListener("load", () => {
337
- try {
338
- frame.contentWindow?.addEventListener("keydown", fullscreenShortcut, listening);
339
- }
340
- catch { /* A frame from another origin keeps its keys. */ }
341
- }, listening);
342
- viewer.insertBefore(frame, originalReturn);
343
- return frame;
344
- }
345
328
  }
@@ -73,6 +73,26 @@
73
73
  white-space: nowrap;
74
74
  }
75
75
 
76
+ .back {
77
+ position: fixed;
78
+ z-index: 3;
79
+ top: max(12px, env(safe-area-inset-top));
80
+ left: max(12px, env(safe-area-inset-left));
81
+ color: #a8a8a8;
82
+ font-size: 12px;
83
+ text-decoration: underline;
84
+ text-decoration-thickness: 1px;
85
+ text-underline-offset: 3px;
86
+ }
87
+ .back:hover,
88
+ .back:focus-visible {
89
+ color: #fff;
90
+ text-decoration-thickness: 2px;
91
+ }
92
+ .back:focus-visible {
93
+ outline: 1px solid #fff;
94
+ outline-offset: 4px;
95
+ }
76
96
  [hidden] {
77
97
  display: none !important;
78
98
  }
@@ -80,6 +100,7 @@
80
100
  <script type="module" src="click-tracking-page.js"></script>
81
101
  </head>
82
102
  <body>
103
+ <a class="back" id="back-link" href="index.html">← back to skyline</a>
83
104
  <canvas id="skyline" role="img" aria-label="Interactive WebGL rendering of the Chicago skyline"></canvas>
84
105
  <p class="loading" id="loading" role="status">preparing WebGL building layers…</p>
85
106
  <div class="tooltip" id="tooltip" aria-hidden="true" hidden></div>
@@ -435,7 +456,7 @@
435
456
  }
436
457
 
437
458
  const sourceRoot = sourceDocument.documentElement;
438
- sourceRoot.querySelectorAll("script, #building-tooltip").forEach((element) => element.remove());
459
+ sourceRoot.querySelectorAll("script, #building-tooltip, #back-link").forEach((element) => element.remove());
439
460
  sourceRoot.setAttribute("width", "850");
440
461
  sourceRoot.setAttribute("height", "278");
441
462
  const sourceHost = document.createElement("div");