@johnmorrisdotca/kyogijo-stadiums 0.39.0 → 0.40.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 +18 -0
- package/README.md +1 -1
- package/dist/crowd.draw.d.ts +5 -0
- package/dist/crowd.draw.js +10 -8
- package/dist/draw.js +2 -1
- package/dist/flythrough.words.js +5 -5
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/strings.js +1 -1
- package/dist/turn-entry.d.ts +2 -0
- package/dist/turn-entry.js +1 -0
- package/dist/turn.style.js +4 -2
- package/dist/types.d.ts +7 -4
- package/dist/venue.d.ts +5 -0
- package/dist/venue.js +9 -9
- package/dist/venue.lighting.d.ts +48 -6
- package/dist/venue.lighting.js +29 -5
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,24 @@ All notable changes to this project are written here. The format follows
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.40.0] - 2026-10-21
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **The named lighting presets** ([the presets](./docs/venues.md#the-lighting-presets)): `lighting: "game" | "intro" | "concert"` join `"night"` and `"lightsDown"`. `game` is white light with the house half lit (a light veil, `u-veil-half`) and a pool of white light round the surface, `intro` the house dark with the home team's colour washed over the surface and the visitors' (the second colour) in the aisle beams, `concert` the house dark with warm amber beams and a purple surface. The presets are a table of constants, `LIGHT_PRESETS` (each preset's `house`, `aisles`, `pool`, and wash and beam colours), with `LIGHTING_PRESETS` (the names) and `LIGHT_COLORS` (the named colours); `LIGHT_PRESETS`, `LIGHTING_PRESETS`, `LIGHT_COLORS` and `resolveLighting` are exported from the main entry and from `/turn` (the 0.39.0 notes named `LIGHT_COLORS` without exporting it), and `WASH` from `/turn`. The `intro`'s team colours are the package's where it has them: the crowd's `home` and `away`, else the colours of a score's two teams, else blue and amber. `lighting: { preset, colors }` passes colours (the first stands for the home team's, the second for the visitors'), and `wash` and `aisles` win over them, for any preset. `resolveLighting(option, team)` now answers `{ preset, house, aisles, pool, beam, wash }`. `TurnModel.lighting` and the view's `data-lighting` say the preset (the stylesheet has a rule for `game` and one for the three dark ones); in the plan the stands' group has `ky-half` or `ky-down`. The `celebration` (colours chasing round the bowl) is to come. Off by default, and a drawing without lighting is exactly what it was.
|
|
15
|
+
- **A Lighting choice on the demo**, in place of the Night and Lights down buttons (kept in the address as `lighting=intro` and so on, with `wash=` for the colour of light over the preset's own; an old address's `night=1` and `lights=1` still work): a choice in the bar over the venues page's view and the home page's featured arena, and on the stadiums, tournament layouts and district pages. The intro is shown with sample team colours (a red and a blue that are nobody's). In 3D a change goes in while the view turns, without stopping it or sending it back.
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **A test that raced another** (`src/docs-language.test.js`): it walks the Markdown files from the root, and met the docs examples' scratch folder `.cache` while that test was removing it, so that `pnpm check` failed now and then with an error reading a file that had just gone. `.cache` is skipped.
|
|
20
|
+
- **The demo's selects were 24 pixels high on a phone in WebKit** (`e2e/looks.demo.mjs`, "every control is a finger wide", failing on `webkit-phone` since 0.39.0): the bar's colour choice took the chip class, whose `display: inline-flex` WebKit does not honour on a select. The bar's selects are `display: inline-block`, 44 pixels high, no wider than 12 rem (they had taken the venue choice's 16 rem minimum).
|
|
21
|
+
|
|
22
|
+
## [0.39.1] - 2026-10-21
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **Japanese wording, from a native-quality review**: spectator seating is `観客席` everywhere in the demo and the fly-through (the fly-through's Bowl stage and the venues page's Stands toggle were `客席`, and the "tiers" labels are now `観客席の層数`); the fly-through's Rink stage is `アイスリンク` (and the atlas's rink label), and its badge is `プレーのイメージ` (was `模擬プレー(イメージ)`); the night lighting is `夜間照明` and its toggle `夜間` (was `ナイト`, which also means a court colour and reads as "knight"); the centre-hung scoreboard is `センターハングビジョン(吊り下げ式スコアボード)` (`センタービジョン` reads as the centre-field screen in baseball); two fly-through sentences read more naturally. English is unchanged.
|
|
27
|
+
|
|
10
28
|
## [0.39.0] - 2026-10-21
|
|
11
29
|
|
|
12
30
|
### Added
|
package/README.md
CHANGED
|
@@ -581,7 +581,7 @@ console.log(layout.needs.length, layout.needs.width);
|
|
|
581
581
|
|
|
582
582
|
### The real venues
|
|
583
583
|
|
|
584
|
-
`crowd: { real: true }` draws an NHL arena in its building: the outline from OpenStreetMap, the rink lying along the building where it says so, and a plausible bowl of the seats, tiers and roof the sources give. All thirty-two arenas of the league, division by division ([the real venues](./docs/venues.md)). `boards: true` adds LED ribbon boards and a hung scoreboard, generic content ([LED boards](./docs/venues.md#led-boards)). In 3D the demo's [venues page](https://johnmorrisdotca.github.io/kyogijo-stadiums/venues.html) turns while the pointer is over it, with the stands, walls, roof, LED boards,
|
|
584
|
+
`crowd: { real: true }` draws an NHL arena in its building: the outline from OpenStreetMap, the rink lying along the building where it says so, and a plausible bowl of the seats, tiers and roof the sources give. All thirty-two arenas of the league, division by division ([the real venues](./docs/venues.md)). `boards: true` adds LED ribbon boards and a hung scoreboard, generic content ([LED boards](./docs/venues.md#led-boards)). In 3D the demo's [venues page](https://johnmorrisdotca.github.io/kyogijo-stadiums/venues.html) turns while the pointer is over it, with the stands, walls, roof, LED boards, lighting, building, markings and labels switched on the view while it turns.
|
|
585
585
|
|
|
586
586
|
```ts
|
|
587
587
|
import { drawKyogijo } from "@johnmorrisdotca/kyogijo-stadiums";
|
package/dist/crowd.draw.d.ts
CHANGED
|
@@ -11,6 +11,11 @@ export interface DrawInput {
|
|
|
11
11
|
density: number;
|
|
12
12
|
fine: boolean;
|
|
13
13
|
ground: string;
|
|
14
|
+
/** The teams' colours of the drawing's score, where it has them: what a lighting's team colours are (the crowd's own `home` and `away` come first). */
|
|
15
|
+
team?: {
|
|
16
|
+
home?: string;
|
|
17
|
+
away?: string;
|
|
18
|
+
};
|
|
14
19
|
}
|
|
15
20
|
/** The building of a real venue and, where its rink's orientation is known, a small arrow with an N that says where north lies. The N is a path of three strokes, so that no font is needed. */
|
|
16
21
|
export declare function realMarkup(real: RealShell): string;
|
package/dist/crowd.draw.js
CHANGED
|
@@ -197,12 +197,12 @@ export function drawCrowd(stands, o) {
|
|
|
197
197
|
for (const s of stands.sectors)
|
|
198
198
|
body += sector(s, id, fine, density);
|
|
199
199
|
// The house is down: a dark veil over the seats, under the aisles' lights.
|
|
200
|
-
const light = stands.gallery === true ? undefined : resolveLighting(crowd.lighting);
|
|
201
|
-
const night = light?.
|
|
202
|
-
const down = light?.
|
|
200
|
+
const light = stands.gallery === true ? undefined : resolveLighting(crowd.lighting, { home: crowd.home ?? o.team?.home, away: crowd.away ?? o.team?.away });
|
|
201
|
+
const night = light?.aisles === "dots";
|
|
202
|
+
const down = light?.aisles === "beams";
|
|
203
203
|
if (light !== undefined)
|
|
204
204
|
for (const ring of stands.rings)
|
|
205
|
-
body += el("path", { class:
|
|
205
|
+
body += el("path", { class: light.house === "dark" ? "ky-cr-veil ky-cr-veil-down" : light.house === "half" ? "ky-cr-veil ky-cr-veil-half" : "ky-cr-veil", d: path(ring) });
|
|
206
206
|
if (fine) {
|
|
207
207
|
for (const ring of stands.rings) {
|
|
208
208
|
if (stands.gallery === true)
|
|
@@ -211,8 +211,8 @@ export function drawCrowd(stands, o) {
|
|
|
211
211
|
body += rows(ring) + aisles(ring, night);
|
|
212
212
|
else {
|
|
213
213
|
// The lights down: the front of each tier edged with light, each stair aisle a beam from above with its rails (a vomitory a broader one).
|
|
214
|
-
body += rows(ring) + (ring.hole === null ? "" : el("path", { class: "ky-cr-edge", d: outlinePath(ring.hole), fill: "none", stroke: light.
|
|
215
|
-
ring.aisles.forEach(([[x0, y0], [x1, y1]], i) => (body += beamSvg([x0, y0], [x1, y1], light.
|
|
214
|
+
body += rows(ring) + (ring.hole === null ? "" : el("path", { class: "ky-cr-edge", d: outlinePath(ring.hole), fill: "none", stroke: light.beam, "stroke-opacity": 0.6, "stroke-width": 0.6 }));
|
|
215
|
+
ring.aisles.forEach(([[x0, y0], [x1, y1]], i) => (body += beamSvg([x0, y0], [x1, y1], light.beam, "ky-cr-beam", i % 4 === 0)));
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
}
|
|
@@ -242,7 +242,7 @@ export function drawCrowd(stands, o) {
|
|
|
242
242
|
pool += el("radialGradient", { id: `${id}-wash`, cx: 0.5, cy: 0.5, r: 0.72 }, el("stop", { offset: 0, "stop-color": light.wash, "stop-opacity": WASH.middle }) + el("stop", { offset: 1, "stop-color": light.wash, "stop-opacity": WASH.edge }));
|
|
243
243
|
over += el("rect", { class: "ky-cr-wash", x: n1(b.x), y: n1(b.y), width: n1(b.w), height: n1(b.h), rx: stands.sport === "nhl" ? NHL.cornerRadius : undefined, fill: `url(#${id}-wash)` });
|
|
244
244
|
}
|
|
245
|
-
if (
|
|
245
|
+
if (light?.pool === true) {
|
|
246
246
|
const b = stands.box;
|
|
247
247
|
const [w, h] = [b.w + 2 * POOL.reach, b.h + 2 * POOL.reach];
|
|
248
248
|
pool += el("radialGradient", { id: `${id}-pool`, cx: 0.5, cy: 0.5, r: 0.5 }, [[0, 0], [POOL.edge - 0.12, 0], [POOL.edge, POOL.strength], [1, 0]].map(([offset, opacity]) => el("stop", { offset, "stop-color": "#fff4dc", "stop-opacity": opacity })).join(""));
|
|
@@ -254,7 +254,7 @@ export function drawCrowd(stands, o) {
|
|
|
254
254
|
const [x0, y0, x1, y1] = g.box;
|
|
255
255
|
body += el("rect", { class: `ky-cr-${g.kind}`, x: n1(x0), y: n1(y0), width: n1(x1 - x0), height: n1(y1 - y0), rx: g.kind === "bench" ? 1 : undefined });
|
|
256
256
|
}
|
|
257
|
-
return { defs: (fine && (stands.gallery !== true || density > 0) ? patterns(id, crowd, density, tifo.home || tifo.away ? tifo : undefined, stands.gallery === true || stands.real !== undefined) : "") + pool, markup: el("g", { class:
|
|
257
|
+
return { defs: (fine && (stands.gallery !== true || density > 0) ? patterns(id, crowd, density, tifo.home || tifo.away ? tifo : undefined, stands.gallery === true || stands.real !== undefined) : "") + pool, markup: el("g", { class: light === undefined ? "ky-crowd" : light.house === "dark" ? "ky-crowd ky-night ky-down" : light.house === "half" ? "ky-crowd ky-night ky-half" : "ky-crowd ky-night" }, body) + lit, over };
|
|
258
258
|
}
|
|
259
259
|
/** A block of visitors or a card display, a polygon over the band it is in. */
|
|
260
260
|
function sector(s, id, fine, density) {
|
|
@@ -297,6 +297,8 @@ export const KYOGIJO_CROWD_STYLE = `
|
|
|
297
297
|
.kyogijo .ky-night{--ky-cr-bed:#11151a;--ky-cr-empty:#2a313a;--ky-cr-gap:#020304;--ky-cr-conc:#171c22;--ky-cr-rim:#07090c}
|
|
298
298
|
.kyogijo .ky-cr-veil{fill:#04060a;fill-opacity:.6}
|
|
299
299
|
.kyogijo .ky-cr-veil-down{fill-opacity:.8}
|
|
300
|
+
.kyogijo .ky-cr-veil-half{fill-opacity:.3}
|
|
301
|
+
.kyogijo .ky-half{--ky-cr-bed:#2a3039;--ky-cr-empty:#4a535f;--ky-cr-gap:#0a0c0f;--ky-cr-conc:#2a3038}
|
|
300
302
|
.kyogijo .ky-cr-beam,.kyogijo .ky-cr-edge{stroke-linecap:butt}
|
|
301
303
|
.kyogijo .ky-night .ky-cr-aisle{stroke:#ffd9a3;stroke-opacity:.95;stroke-dasharray:1.1 3.4;stroke-linecap:round}
|
|
302
304
|
.kyogijo .ky-night .ky-cr-vom{stroke:#7dffb0;stroke-opacity:.6;stroke-dasharray:none}
|
package/dist/draw.js
CHANGED
|
@@ -61,6 +61,7 @@ import { overlayMarkup, placeBoard, resolveBoard } from "./overlay.js";
|
|
|
61
61
|
import { KYOGIJO_HARDWOOD_STYLE, resolveHardwood } from "./hardwood.js";
|
|
62
62
|
import { WALL_SEATS, densityOf, layoutOf as crowdLayout, resolveCrowd } from "./crowd.js";
|
|
63
63
|
import { drawCrowd, KYOGIJO_CROWD_STYLE } from "./crowd.draw.js";
|
|
64
|
+
import { teamColors } from "./venue.lighting.js";
|
|
64
65
|
import { parkLayout } from "./crowd.park.js";
|
|
65
66
|
import { featureColours, featureStyle } from "./features.js";
|
|
66
67
|
import { isLook, lookStyle } from "./look.js";
|
|
@@ -489,7 +490,7 @@ function buildCrowded(o, portrait, id, score, scored, extra, crowd) {
|
|
|
489
490
|
const bg = /class="([^"]*)"/.exec(first)?.[1] ?? "ky-apron";
|
|
490
491
|
// A gallery is empty unless the options say how full: its seats are the detail.
|
|
491
492
|
const taken = stands.gallery === true && crowd.density === undefined && crowd.attendance === undefined ? 0 : densityOf(crowd, seats, ground);
|
|
492
|
-
const drawn = drawCrowd(stands, { id, crowd, density: taken, fine, ground: bg });
|
|
493
|
+
const drawn = drawCrowd(stands, { id, crowd, density: taken, fine, ground: bg, team: teamColors(o) });
|
|
493
494
|
surface.base = first + drawn.markup + surface.base.slice(first.length);
|
|
494
495
|
surface.defs += drawn.defs;
|
|
495
496
|
surface.lines += drawn.over;
|
package/dist/flythrough.words.js
CHANGED
|
@@ -26,14 +26,14 @@ export const FLYTHROUGH_WORDS = {
|
|
|
26
26
|
ja: {
|
|
27
27
|
title: "フライスルー:{arena}",
|
|
28
28
|
region: "フライスルー",
|
|
29
|
-
about: "地図から{place}の{arena}まで進むフライスルーです。地図、都市、3D
|
|
29
|
+
about: "地図から{place}の{arena}まで進むフライスルーです。地図、都市、3Dのアリーナ、スタンドの上空から中へ入る場面、観客席から見たアイスリンク、氷上の短い模擬プレーの順に見られます。ボタンまたはキーで、再生・一時停止、前後の場面への移動、場面の選択ができます。",
|
|
30
30
|
stage: {
|
|
31
31
|
map: { name: "地図", text: "{arena}は{place}にあります。" },
|
|
32
32
|
city: { name: "都市", text: "{arena}の建物を真上から見たところです(OpenStreetMapの記録による)。" },
|
|
33
33
|
arena: { name: "アリーナ", text: "{arena}を3Dで回転させて表示しています。" },
|
|
34
|
-
bowl: { name: "
|
|
35
|
-
rink: { name: "
|
|
36
|
-
game: { name: "試合", text: "
|
|
34
|
+
bowl: { name: "観客席", text: "屋根を取り払い、スタンドの上空から中へ入ります。{seats}席・{tiers}層と推定したスタンドで、実際の座席表ではありません。" },
|
|
35
|
+
rink: { name: "アイスリンク", text: "スタンドからリンクを見渡した眺めで、ゆっくり回転します。視点の位置と高さは仮のもので、実在の座席ではありません。" },
|
|
36
|
+
game: { name: "試合", text: "イメージ用に作った短い模擬プレーです。各チーム5人のスケーターとゴーリー、そしてパックが氷上を動きます。実際の試合のデータではありません。" },
|
|
37
37
|
},
|
|
38
38
|
announce: "場面{n}/{total}:{name}。{text}",
|
|
39
39
|
play: "再生",
|
|
@@ -44,7 +44,7 @@ export const FLYTHROUGH_WORDS = {
|
|
|
44
44
|
keys: "スペースキーで再生・一時停止。左右の矢印キーで前後の場面へ、数字キーで場面を選び、Homeキーで最初に戻ります。",
|
|
45
45
|
creditMap: "地図:Natural Earth(パブリックドメイン)、chizuで描画。建物の輪郭:(c) OpenStreetMap contributors、ODbL 1.0、openstreetmap.org/copyright。",
|
|
46
46
|
creditPlain: "建物の輪郭:(c) OpenStreetMap contributors、ODbL 1.0、openstreetmap.org/copyright。",
|
|
47
|
-
illustrative: "
|
|
47
|
+
illustrative: "プレーのイメージ",
|
|
48
48
|
still: "この端末は動きを減らす設定のため、各場面を静止画で表示しています。",
|
|
49
49
|
},
|
|
50
50
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { HOME_FIRST, HOME_FIRST_LEAGUES, homeSideFor } from "./homeside.ts";
|
|
|
3
3
|
export { inkOn, luminance, rgbOf, safeColour, safePicture } from "./colour.ts";
|
|
4
4
|
export { safeLogo } from "./logo.ts";
|
|
5
5
|
export { useEmblems } from "./emblems-source.ts";
|
|
6
|
+
export { LIGHTING_PRESETS, LIGHT_COLORS, LIGHT_PRESETS, resolveLighting } from "./venue.lighting.ts";
|
|
6
7
|
export type { EmblemDrawOptions, EmblemId, EmblemRef, EmblemRenderer, EmblemStyleName } from "./emblems-source.ts";
|
|
7
8
|
export { useFlags } from "./flags-source.ts";
|
|
8
9
|
export type { FlagRenderer, FlagRequest, FlagShape } from "./flags-source.ts";
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { HOME_FIRST, HOME_FIRST_LEAGUES, homeSideFor } from "./homeside.js";
|
|
|
4
4
|
export { inkOn, luminance, rgbOf, safeColour, safePicture } from "./colour.js";
|
|
5
5
|
export { safeLogo } from "./logo.js";
|
|
6
6
|
export { useEmblems } from "./emblems-source.js";
|
|
7
|
+
export { LIGHTING_PRESETS, LIGHT_COLORS, LIGHT_PRESETS, resolveLighting } from "./venue.lighting.js";
|
|
7
8
|
export { useFlags } from "./flags-source.js";
|
|
8
9
|
export { OUTCOMES, drawLayers, layerTable } from "./layers.js";
|
|
9
10
|
export { RANGES } from "./ranges.names.js";
|
package/dist/strings.js
CHANGED
|
@@ -1014,7 +1014,7 @@ export const KYOGIJO_STRINGS = {
|
|
|
1014
1014
|
announce: "{name}の視点", announceAngle: "向きは{yaw}度、見下ろす角度は{pitch}度です。",
|
|
1015
1015
|
flat: "このブラウザーでは3D表示ができないため、平面の図を表示しています。",
|
|
1016
1016
|
standing: "3D表示で立って見えるもの:{list}。", item: "{name} {h}", itemSag: "{name} 支柱の位置で{h}(中央は{low})",
|
|
1017
|
-
parts: { scoreboard: "スコアボードの下端", net: "ネット", antennae: "アンテナ", goalposts: "ゴールポスト", netposts: "支柱", hoop: "バスケットゴール", goal: "ゴール", boards: "ボードとガラス", stumps: "ウィケットのスタンプ", pylons: "パイロン", flags: "コーナーフラッグ", fence: "外野フェンス", backstop: "バックネット", "foul-poles": "ファウルポール", "table-legs": "天板", walls: "壁", "starting-blocks": "スタート台", "backstroke-flags": "背泳ぎ用フラッグ", "false-start-rope": "フォルススタートロープ", springboards: "飛板", platforms: "固定台", "judges-stand": "ジャッジ台", hurdles: "ハードル", steeplechase: "障害物", "high-jump": "走高跳の支柱とバー", "pole-vault": "棒高跳の支柱とバー", cage: "円盤投・ハンマー投の囲い", padding: "防護マット", "rink-boards": "フェンス", mound: "土の台", azuchi: "安土", targets: "的", stands: "スタンド", "wall-seats": "壁の上の観客席", roof: "屋根", gallery: "見学席", dais: "上座の台", banner: "垂れ幕", shrine: "神棚", "mat-edge": "畳の厚み", surrounds: "競技エリアのフェンス", officials: "審判席と記録台", judges: "審判員席の名札", deck: "台", "cage-fence": "金網", "cage-posts": "パッド付き支柱", "ring-ropes": "ロープ", "ring-posts": "コーナーポスト", "ribbon-boards": "LEDリボンビジョン", "hung-board": "
|
|
1017
|
+
parts: { scoreboard: "スコアボードの下端", net: "ネット", antennae: "アンテナ", goalposts: "ゴールポスト", netposts: "支柱", hoop: "バスケットゴール", goal: "ゴール", boards: "ボードとガラス", stumps: "ウィケットのスタンプ", pylons: "パイロン", flags: "コーナーフラッグ", fence: "外野フェンス", backstop: "バックネット", "foul-poles": "ファウルポール", "table-legs": "天板", walls: "壁", "starting-blocks": "スタート台", "backstroke-flags": "背泳ぎ用フラッグ", "false-start-rope": "フォルススタートロープ", springboards: "飛板", platforms: "固定台", "judges-stand": "ジャッジ台", hurdles: "ハードル", steeplechase: "障害物", "high-jump": "走高跳の支柱とバー", "pole-vault": "棒高跳の支柱とバー", cage: "円盤投・ハンマー投の囲い", padding: "防護マット", "rink-boards": "フェンス", mound: "土の台", azuchi: "安土", targets: "的", stands: "スタンド", "wall-seats": "壁の上の観客席", roof: "屋根", gallery: "見学席", dais: "上座の台", banner: "垂れ幕", shrine: "神棚", "mat-edge": "畳の厚み", surrounds: "競技エリアのフェンス", officials: "審判席と記録台", judges: "審判員席の名札", deck: "台", "cage-fence": "金網", "cage-posts": "パッド付き支柱", "ring-ropes": "ロープ", "ring-posts": "コーナーポスト", "ribbon-boards": "LEDリボンビジョン", "hung-board": "センターハングビジョン(吊り下げ式スコアボード)" },
|
|
1018
1018
|
},
|
|
1019
1019
|
rules: {
|
|
1020
1020
|
"defensive-zone": "ディフェンディングゾーン",
|
package/dist/turn-entry.d.ts
CHANGED
|
@@ -12,6 +12,8 @@ export type { Box3, Mat4, Placement, TurnPreset, TurnToward, TurnView } from "./
|
|
|
12
12
|
export { describeUprights, heightUnit, planesOf, uprightsFor } from "./uprights.ts";
|
|
13
13
|
export type { UprightOptions, Uprights } from "./uprights.ts";
|
|
14
14
|
export { ROOF } from "./venue.ts";
|
|
15
|
+
export { LIGHTING_PRESETS, LIGHT_COLORS, LIGHT_PRESETS, WASH, resolveLighting } from "./venue.lighting.ts";
|
|
16
|
+
export type { House, LightPreset, Lighting } from "./venue.lighting.ts";
|
|
15
17
|
export type { Venue, VenueBuild, VenueSettings } from "./venue.ts";
|
|
16
18
|
export type { LedBoardOptions, LedBoardPattern, LightingOptions, LightingPreset } from "./types.ts";
|
|
17
19
|
export type { Plane, PartKind, Upright, UprightKind, V3 } from "./turn.kit.ts";
|
package/dist/turn-entry.js
CHANGED
|
@@ -7,3 +7,4 @@ export { KYOGIJO_TURN_STYLE } from "./turn.style.js";
|
|
|
7
7
|
export { CURLING_PRESETS, LONG_PRESETS, NET_PRESETS, PITCH_MAX, STEP, TURN_DEFAULT, TURN_PRESETS, TURN_PRESET_NAMES, ZOOM_MAX, ZOOM_MIN, cameraMatrix, clampView, depthOf, drag, eyeDistance, fit, matrix3d, multiply, nudge, presetOf, presetView, presetsFor, project, step } from "./turn.camera.js";
|
|
8
8
|
export { describeUprights, heightUnit, planesOf, uprightsFor } from "./uprights.js";
|
|
9
9
|
export { ROOF } from "./venue.js";
|
|
10
|
+
export { LIGHTING_PRESETS, LIGHT_COLORS, LIGHT_PRESETS, WASH, resolveLighting } from "./venue.lighting.js";
|
package/dist/turn.style.js
CHANGED
|
@@ -93,11 +93,13 @@ export const KYOGIJO_TURN_STYLE = `
|
|
|
93
93
|
.ky-turn[data-lighting]{--ky-cr-bed:#11151a;--ky-cr-empty:#2a313a;--ky-cr-gap:#020304;--ky-cr-conc:#171c22;--ky-cr-dim:1;--ky-up-fascia:#272c29;--ky-up-ground:#1d211e;--ky-night-aisle:#ffd9a3;--ky-night-exit:#7dffb0;--ky-night-rim:#ffe0b0}
|
|
94
94
|
.ky-turn .u-veil{fill:#04060a;fill-opacity:.62}
|
|
95
95
|
.ky-turn .u-veil-down{fill-opacity:.8}
|
|
96
|
-
.ky-turn
|
|
96
|
+
.ky-turn .u-veil-half{fill-opacity:.3}
|
|
97
|
+
.ky-turn:is([data-lighting=lightsDown],[data-lighting=intro],[data-lighting=concert]){--ky-cr-bed:#0a0d11;--ky-cr-conc:#101419;--ky-up-fascia:#1b1f1d;--ky-up-ground:#15181a}
|
|
98
|
+
.ky-turn[data-lighting=game]{--ky-cr-bed:#2a3039;--ky-cr-empty:#4a535f;--ky-cr-gap:#0a0c0f;--ky-cr-conc:#2a3038;--ky-up-fascia:#3b403c;--ky-up-ground:#242823}
|
|
97
99
|
.ky-turn[data-lighting=night] .ky-cr-aisle{stroke:var(--ky-night-aisle);stroke-opacity:.95;stroke-dasharray:1.1 3.4;stroke-linecap:round}
|
|
98
100
|
.ky-turn[data-lighting=night] .ky-cr-vom{stroke:var(--ky-night-exit);stroke-opacity:.6;stroke-dasharray:none}
|
|
99
101
|
.ky-turn[data-lighting] .u-suite-win{fill:color-mix(in srgb,var(--ky-night-aisle) 50%,#2a2218)}
|
|
100
|
-
.ky-turn[data-lighting=lightsDown] .u-suite-win{fill:color-mix(in srgb,var(--ky-night-aisle) 10%,#0d1116)}
|
|
102
|
+
.ky-turn:is([data-lighting=lightsDown],[data-lighting=intro],[data-lighting=concert]) .u-suite-win{fill:color-mix(in srgb,var(--ky-night-aisle) 10%,#0d1116)}
|
|
101
103
|
.ky-turn[data-lighting] .u-coping{fill:color-mix(in srgb,var(--ky-night-rim) 55%,var(--ky-up-fascia))}
|
|
102
104
|
.ky-turn[data-lighting] .u-suite-ledge{fill:color-mix(in srgb,var(--ky-night-rim) 45%,var(--ky-up-fascia))}
|
|
103
105
|
.ky-turn[data-lighting] .u-clane{stroke:var(--ky-night-rim);stroke-opacity:.4}
|
package/dist/types.d.ts
CHANGED
|
@@ -275,13 +275,16 @@ export type SheetEnd = Side | "top" | "bottom";
|
|
|
275
275
|
/** The shape of a venue's stands round the playing surface. */
|
|
276
276
|
export type CrowdShape = "bowl" | "sides" | "horseshoe" | "grandstand";
|
|
277
277
|
/**
|
|
278
|
-
* The lighting of a venue (`crowd.lighting` in the plan, `venue.lighting` in the 3D view)
|
|
279
|
-
* boards and the scoreboard glowing, the exits and the concourse rim softly lit. `"lightsDown"` is a show's house: nearly black, each stair aisle lit from
|
|
280
|
-
*
|
|
278
|
+
* The lighting of a venue (`crowd.lighting` in the plan, `venue.lighting` in the 3D view): a named preset (`LIGHT_PRESETS`), `true` (the night), or `{ preset, colors, aisles, wash }`. `"night"` dims the house, lights the playing surface and shows small
|
|
279
|
+
* lights along the aisles and stairs, the ribbon boards and the scoreboard glowing, the exits and the concourse rim softly lit. `"game"` is white light with the house half lit. `"lightsDown"` is a show's house: nearly black, each stair aisle lit from
|
|
280
|
+
* above as a beam with a soft falloff on the steps either side, the rails and the front of every step edged with light. `"intro"` is the same house with the home team's colour washed over the surface and the visitors' in the beams (the teams'
|
|
281
|
+
* colours where the options have them, else blue and amber); `"concert"` has warm amber beams and a purple surface. `colors` are one or two colours that stand for the home and the visitors (before the options' teams); `wash` colours the playing surface
|
|
282
|
+
* with a light (a CSS colour, or `white`, `amber`, `purple`, `magenta`, `blue`, `cyan`; the markings stay visible) and `aisles` the beams, and both win over the preset's. `false` is no lighting. Off by default.
|
|
281
283
|
*/
|
|
282
|
-
export type LightingPreset = "night" | "lightsDown";
|
|
284
|
+
export type LightingPreset = "night" | "game" | "lightsDown" | "intro" | "concert";
|
|
283
285
|
export type LightingOptions = LightingPreset | boolean | {
|
|
284
286
|
preset?: LightingPreset;
|
|
287
|
+
colors?: readonly string[];
|
|
285
288
|
aisles?: string;
|
|
286
289
|
wash?: string;
|
|
287
290
|
};
|
package/dist/venue.d.ts
CHANGED
|
@@ -30,6 +30,11 @@ export interface VenueBuild extends VenueSettings {
|
|
|
30
30
|
id: string;
|
|
31
31
|
/** Leave the scoreboard hung over the middle out (a tournament hall has scoreboards of its own). */
|
|
32
32
|
noCentre?: boolean;
|
|
33
|
+
/** The teams' colours the drawing has (a crowd's `home` and `away`, or a score's teams'): what a lighting's team colours are. */
|
|
34
|
+
team?: {
|
|
35
|
+
home?: string;
|
|
36
|
+
away?: string;
|
|
37
|
+
};
|
|
33
38
|
}
|
|
34
39
|
/** What the venue is made of: the things that stand, and the patterns they are drawn with (the contents of a `defs`). */
|
|
35
40
|
export interface Venue {
|
package/dist/venue.js
CHANGED
|
@@ -10,7 +10,7 @@ import { groundById } from "./grounds.js";
|
|
|
10
10
|
import { ARC_STEPS, clipAround, clipConvex, clipSegment, areaOf, pointList, raked, slopeOf, stripsOf, tidy } from "./venue.geom.js";
|
|
11
11
|
import { APRON_RISE, apronPlanes, backEdges, backWall, concourseFloor, rimAt, suiteWall } from "./venue.fill.js";
|
|
12
12
|
import { firstHit, realBuilding } from "./venue.real.js";
|
|
13
|
-
import { beamSvg, edgeSvg, lightPool, lightWash, resolveLighting } from "./venue.lighting.js";
|
|
13
|
+
import { beamSvg, edgeSvg, lightPool, lightWash, resolveLighting, teamColors } from "./venue.lighting.js";
|
|
14
14
|
import { centreBoard, fasciaRibbon, hangsOver, ledStrip, resolveBoards, ribbonHigh, ribbonShare, tierLinks } from "./venue.boards.js";
|
|
15
15
|
import { n, shy, wall } from "./turn.kit.js";
|
|
16
16
|
export const NO_VENUE = { items: [], defs: "", reach: 0 };
|
|
@@ -38,7 +38,7 @@ export function standsVenue(o, v, lift) {
|
|
|
38
38
|
const crowd = resolveCrowd(o.crowd);
|
|
39
39
|
if (stands === undefined || crowd === undefined || stands.gallery === true)
|
|
40
40
|
return NO_VENUE;
|
|
41
|
-
return standsVenueOf(stands, crowd, { sport: o.sport, detail: o.detail, ground: o.ground }, v, lift);
|
|
41
|
+
return standsVenueOf(stands, crowd, { sport: o.sport, detail: o.detail, ground: o.ground }, { ...v, team: v.team ?? teamColors(o, crowd) }, lift);
|
|
42
42
|
}
|
|
43
43
|
/**
|
|
44
44
|
* The stands the model says (`crowdStands`, or the stands of a tournament layout's hall) as planes: what `standsVenue` makes of a surface's, for stands that were worked out some other way. `o` is the little of the
|
|
@@ -76,17 +76,17 @@ export function standsVenueOf(stands, crowd, o, v, lift) {
|
|
|
76
76
|
svg += fine ? `<polygon fill="url(#${pid}-cr-${s.kind === "tifo-home" ? "th" : "ta"})" points="${points}"/>` : `<polygon class="${s.kind === "tifo-home" ? "u-th" : "u-ta"}" points="${points}"/>`;
|
|
77
77
|
}
|
|
78
78
|
if (light !== undefined)
|
|
79
|
-
svg += `<polygon class="${
|
|
79
|
+
svg += `<polygon class="${light.house === "dark" ? "u-veil u-veil-down" : light.house === "half" ? "u-veil u-veil-half" : "u-veil"}" points="${pointList(corners)}"/>`;
|
|
80
80
|
// The lights down: the front of each step is edged with light, and each stair aisle is a beam from above with the rails beside it (the aisle lines the stands' dark ones are, are left out).
|
|
81
81
|
if (down && light !== undefined) {
|
|
82
82
|
if (corners.length === 4)
|
|
83
|
-
svg += edgeSvg(corners[0], corners[1], light.
|
|
83
|
+
svg += edgeSvg(corners[0], corners[1], light.beam, "u-edge");
|
|
84
84
|
if (fine) {
|
|
85
85
|
ring.aisles.forEach(([a, b], i) => {
|
|
86
86
|
const seg = clipSegment(a, b, piece);
|
|
87
87
|
if (seg === undefined || Math.hypot(seg[1][0] - seg[0][0], seg[1][1] - seg[0][1]) < 0.5)
|
|
88
88
|
return;
|
|
89
|
-
svg += beamSvg(local(seg[0]), local(seg[1]), light.
|
|
89
|
+
svg += beamSvg(local(seg[0]), local(seg[1]), light.beam, "u-beam", i % 4 === 0);
|
|
90
90
|
});
|
|
91
91
|
}
|
|
92
92
|
}
|
|
@@ -116,9 +116,9 @@ export function standsVenueOf(stands, crowd, o, v, lift) {
|
|
|
116
116
|
const links = tierLinks(stands);
|
|
117
117
|
for (const l of links)
|
|
118
118
|
chained.add(l.after);
|
|
119
|
-
const light = resolveLighting(v.lighting !== undefined ? v.lighting : crowd.lighting);
|
|
120
|
-
const night = light?.
|
|
121
|
-
const down = light?.
|
|
119
|
+
const light = resolveLighting(v.lighting !== undefined ? v.lighting : crowd.lighting, v.team ?? teamColors({}, crowd));
|
|
120
|
+
const night = light?.aisles === "dots";
|
|
121
|
+
const down = light?.aisles === "beams";
|
|
122
122
|
const boards = resolveBoards(v.boards !== undefined ? v.boards : crowd.boards, { home: crowd.home, away: crowd.away }, light !== undefined);
|
|
123
123
|
const ribbons = [];
|
|
124
124
|
/** How far along the ribbon of one level the next piece of it starts, in feet, so that its panels carry on. */
|
|
@@ -208,7 +208,7 @@ export function standsVenueOf(stands, crowd, o, v, lift) {
|
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
// The surface is lit: a pool of light on the floor round it, under the seats.
|
|
211
|
-
if (
|
|
211
|
+
if (light?.pool === true)
|
|
212
212
|
seatPlanes.push(lightPool("night-pool", stands.box, lift + APRON_RISE + 0.03, light?.wash));
|
|
213
213
|
// A colour of light on the surface (a show's wash), over the markings, which stay visible through it.
|
|
214
214
|
if (light?.wash !== undefined)
|
package/dist/venue.lighting.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { type Plane } from "./turn.kit.ts";
|
|
2
2
|
import type { LightingOptions, LightingPreset } from "./types.ts";
|
|
3
|
-
|
|
4
|
-
/** The named colours of light: `wash` and `aisles` take these by name (ours, a little saturated, for a light seen on dark). */
|
|
3
|
+
/** The named colours of light: `wash`, `aisles` and `colors` take these by name (ours, a little saturated, for a light seen on dark). */
|
|
5
4
|
export declare const LIGHT_COLORS: {
|
|
6
5
|
readonly white: "#fff6e6";
|
|
7
6
|
readonly amber: "#ffb830";
|
|
@@ -10,14 +9,57 @@ export declare const LIGHT_COLORS: {
|
|
|
10
9
|
readonly blue: "#2b7bff";
|
|
11
10
|
readonly cyan: "#27d6ff";
|
|
12
11
|
};
|
|
13
|
-
/**
|
|
12
|
+
/** How dark the house is: `half` (a light veil, the game's), `dim` (the night's) or `dark` (a show's). */
|
|
13
|
+
export type House = "half" | "dim" | "dark";
|
|
14
|
+
/**
|
|
15
|
+
* A named lighting. `house` is how dark the stands are; `aisles` how the aisles are lit (`none`, small `dots`, or a `beam` of light from above down each); `pool` whether a pool of light lies on the floor round the surface; `wash` and `beam` are the colours
|
|
16
|
+
* of the light on the surface and of the beams: a colour (a name of `LIGHT_COLORS`), or `home` and `away`, the teams' colours where the options have them (`crowd.home` and `crowd.away`, the colours of a score's teams), else `fallback`'s.
|
|
17
|
+
*/
|
|
18
|
+
export interface LightPreset {
|
|
19
|
+
house: House;
|
|
20
|
+
aisles: "none" | "dots" | "beams";
|
|
21
|
+
pool: boolean;
|
|
22
|
+
wash?: keyof typeof LIGHT_COLORS | "home" | "away";
|
|
23
|
+
beam?: keyof typeof LIGHT_COLORS | "home" | "away";
|
|
24
|
+
/** What `home` and `away` are where the options name no team colour. */
|
|
25
|
+
fallback?: {
|
|
26
|
+
home: keyof typeof LIGHT_COLORS;
|
|
27
|
+
away: keyof typeof LIGHT_COLORS;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The named lightings. `night`: the calm dim house with small lights along the aisles. `game`: white light, the house half lit, a pool of light round the surface. `lightsDown`: the house nearly black, a white beam down each aisle. `intro`: the
|
|
32
|
+
* house dark, the home team's colour washed over the surface and the visitors' (the second colour) in the beams. `concert`: warm amber beams and a purple surface. (The `celebration` of the plan, colours chasing round the bowl, is a later one.)
|
|
33
|
+
*/
|
|
34
|
+
export declare const LIGHT_PRESETS: Readonly<Record<LightingPreset, LightPreset>>;
|
|
35
|
+
export declare const LIGHTING_PRESETS: readonly LightingPreset[];
|
|
36
|
+
/** The lighting as asked, with every part's value. */
|
|
14
37
|
export interface Lighting {
|
|
15
38
|
preset: LightingPreset;
|
|
16
|
-
|
|
39
|
+
house: House;
|
|
40
|
+
aisles: "none" | "dots" | "beams";
|
|
41
|
+
pool: boolean;
|
|
42
|
+
/** The colour of the beams. */
|
|
43
|
+
beam: string;
|
|
44
|
+
/** The surface's colour of light (none for the surface as it is). */
|
|
17
45
|
wash: string | undefined;
|
|
18
46
|
}
|
|
19
|
-
/** The
|
|
20
|
-
export declare function
|
|
47
|
+
/** The teams' colours the options have: a score's teams' `color`, over which a crowd's `home` and `away` stand. */
|
|
48
|
+
export declare function teamColors(o: object, crowd?: {
|
|
49
|
+
home?: string;
|
|
50
|
+
away?: string;
|
|
51
|
+
}): {
|
|
52
|
+
home?: string;
|
|
53
|
+
away?: string;
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* The lighting an option asks for: a preset's name, `true` for the first (night), or `{ preset, colors, aisles, wash }`, or `undefined` for none (false, nothing, an unknown name). A colour comes from, in order: `wash` or `aisles`, `colors` (the first
|
|
57
|
+
* is what the preset's `home` is, the second its `away`), the teams' colours (`team`), the preset's own.
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveLighting(ask: LightingOptions | undefined | null, team?: {
|
|
60
|
+
home?: string;
|
|
61
|
+
away?: string;
|
|
62
|
+
}): Lighting | undefined;
|
|
21
63
|
/** How far the pool of light round the surface reaches beyond its box, in feet, and the share of the pool that is bright (the surface's own edge). The surface itself stays as drawn: the pool is brightest just outside its markings. */
|
|
22
64
|
export declare const POOL: {
|
|
23
65
|
readonly reach: 20;
|
package/dist/venue.lighting.js
CHANGED
|
@@ -4,19 +4,43 @@
|
|
|
4
4
|
// Pure: data in, planes out.
|
|
5
5
|
import { flat, n } from "./turn.kit.js";
|
|
6
6
|
import { safeColor } from "./venue.boards.js";
|
|
7
|
-
|
|
8
|
-
/** The named colours of light: `wash` and `aisles` take these by name (ours, a little saturated, for a light seen on dark). */
|
|
7
|
+
/** The named colours of light: `wash`, `aisles` and `colors` take these by name (ours, a little saturated, for a light seen on dark). */
|
|
9
8
|
export const LIGHT_COLORS = { white: "#fff6e6", amber: "#ffb830", purple: "#9b4dff", magenta: "#ff2bd6", blue: "#2b7bff", cyan: "#27d6ff" };
|
|
9
|
+
/**
|
|
10
|
+
* The named lightings. `night`: the calm dim house with small lights along the aisles. `game`: white light, the house half lit, a pool of light round the surface. `lightsDown`: the house nearly black, a white beam down each aisle. `intro`: the
|
|
11
|
+
* house dark, the home team's colour washed over the surface and the visitors' (the second colour) in the beams. `concert`: warm amber beams and a purple surface. (The `celebration` of the plan, colours chasing round the bowl, is a later one.)
|
|
12
|
+
*/
|
|
13
|
+
export const LIGHT_PRESETS = {
|
|
14
|
+
night: { house: "dim", aisles: "dots", pool: true },
|
|
15
|
+
game: { house: "half", aisles: "none", pool: true },
|
|
16
|
+
lightsDown: { house: "dark", aisles: "beams", pool: false },
|
|
17
|
+
intro: { house: "dark", aisles: "beams", pool: false, wash: "home", beam: "away", fallback: { home: "blue", away: "amber" } },
|
|
18
|
+
concert: { house: "dark", aisles: "beams", pool: false, wash: "purple", beam: "amber" },
|
|
19
|
+
};
|
|
20
|
+
export const LIGHTING_PRESETS = Object.keys(LIGHT_PRESETS);
|
|
10
21
|
const colorOf = (value) => (typeof value === "string" && Object.hasOwn(LIGHT_COLORS, value) ? LIGHT_COLORS[value] : safeColor(value));
|
|
11
|
-
/** The
|
|
12
|
-
export function
|
|
22
|
+
/** The teams' colours the options have: a score's teams' `color`, over which a crowd's `home` and `away` stand. */
|
|
23
|
+
export function teamColors(o, crowd) {
|
|
24
|
+
const teams = o;
|
|
25
|
+
return { home: safeColor(crowd?.home) ?? safeColor(teams.home?.color), away: safeColor(crowd?.away) ?? safeColor(teams.away?.color) };
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* The lighting an option asks for: a preset's name, `true` for the first (night), or `{ preset, colors, aisles, wash }`, or `undefined` for none (false, nothing, an unknown name). A colour comes from, in order: `wash` or `aisles`, `colors` (the first
|
|
29
|
+
* is what the preset's `home` is, the second its `away`), the teams' colours (`team`), the preset's own.
|
|
30
|
+
*/
|
|
31
|
+
export function resolveLighting(ask, team = {}) {
|
|
13
32
|
if (ask === undefined || ask === null || ask === false)
|
|
14
33
|
return undefined;
|
|
15
34
|
const o = typeof ask === "object" ? ask : {};
|
|
16
35
|
const name = typeof ask === "string" ? ask : ask === true ? "night" : o.preset ?? "night";
|
|
17
36
|
if (!LIGHTING_PRESETS.includes(name))
|
|
18
37
|
return undefined;
|
|
19
|
-
|
|
38
|
+
const preset = name;
|
|
39
|
+
const base = LIGHT_PRESETS[preset];
|
|
40
|
+
const given = (Array.isArray(o.colors) ? o.colors : []).map(colorOf).filter((c) => c !== undefined);
|
|
41
|
+
const side = (which) => (which === "home" ? given[0] ?? team.home : given[1] ?? team.away) ?? LIGHT_COLORS[base.fallback?.[which] ?? (which === "home" ? "blue" : "amber")];
|
|
42
|
+
const pick = (token) => (token === undefined ? undefined : token === "home" || token === "away" ? side(token) : LIGHT_COLORS[token]);
|
|
43
|
+
return { preset, house: base.house, aisles: base.aisles, pool: base.pool, beam: colorOf(o.aisles) ?? pick(base.beam) ?? LIGHT_COLORS.white, wash: colorOf(o.wash) ?? pick(base.wash) };
|
|
20
44
|
}
|
|
21
45
|
/** How far the pool of light round the surface reaches beyond its box, in feet, and the share of the pool that is bright (the surface's own edge). The surface itself stays as drawn: the pool is brightest just outside its markings. */
|
|
22
46
|
export const POOL = { reach: 20, edge: 0.7, strength: 0.34 };
|
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.
|
|
2
|
+
export declare const VERSION = "0.40.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.
|
|
2
|
+
export const VERSION = "0.40.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@johnmorrisdotca/kyogijo-stadiums",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.40.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",
|