@johnmorrisdotca/dougu-sports 0.0.1 → 0.1.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 +24 -1
- package/LICENSES/Apache-2.0.txt +202 -55
- package/LICENSES/CC-BY-3.0.txt +319 -0
- package/LICENSES/README.md +4 -3
- package/LICENSES/upstream/game-icons.license.txt +45 -0
- package/LICENSES/upstream/noto-emoji-2D-svg.LICENSE +13 -0
- package/LICENSES/upstream/pictogrammers-mdi.LICENSE +20 -0
- package/NOTICE.md +92 -3
- package/README.md +104 -69
- package/dist/emblems/award/badge.d.ts +2 -0
- package/dist/emblems/award/badge.js +5 -0
- package/dist/emblems/award/crown.d.ts +2 -0
- package/dist/emblems/award/crown.js +5 -0
- package/dist/emblems/award/medal.d.ts +2 -2
- package/dist/emblems/award/medal.js +5 -19
- package/dist/emblems/award/shield.d.ts +2 -0
- package/dist/emblems/award/shield.js +5 -0
- package/dist/emblems/award/star.d.ts +2 -0
- package/dist/emblems/award/star.js +5 -0
- package/dist/emblems/ball/ball.afl.d.ts +1 -0
- package/dist/emblems/ball/ball.afl.js +24 -0
- package/dist/emblems/ball/ball.baseball.d.ts +1 -0
- package/dist/emblems/ball/ball.baseball.js +14 -0
- package/dist/emblems/ball/ball.basketball.d.ts +7 -0
- package/dist/emblems/ball/ball.basketball.js +32 -0
- package/dist/emblems/ball/ball.basketball3x3.d.ts +1 -0
- package/dist/emblems/ball/ball.basketball3x3.js +10 -0
- package/dist/emblems/ball/ball.basketball6.d.ts +1 -0
- package/dist/emblems/ball/ball.basketball6.js +10 -0
- package/dist/emblems/ball/ball.core.d.ts +105 -0
- package/dist/emblems/ball/ball.core.js +66 -0
- package/dist/emblems/ball/ball.cricket.d.ts +5 -0
- package/dist/emblems/ball/ball.cricket.js +31 -0
- package/dist/emblems/ball/ball.curlingstone.d.ts +3 -0
- package/dist/emblems/ball/ball.curlingstone.js +46 -0
- package/dist/emblems/ball/ball.discus.d.ts +1 -0
- package/dist/emblems/ball/ball.discus.js +24 -0
- package/dist/emblems/ball/ball.engine.d.ts +114 -0
- package/dist/emblems/ball/ball.engine.js +342 -0
- package/dist/emblems/ball/ball.family.dotted.d.ts +27 -0
- package/dist/emblems/ball/ball.family.dotted.js +20 -0
- package/dist/emblems/ball/ball.family.panelled.d.ts +7 -0
- package/dist/emblems/ball/ball.family.panelled.js +60 -0
- package/dist/emblems/ball/ball.family.prolate.d.ts +16 -0
- package/dist/emblems/ball/ball.family.prolate.js +29 -0
- package/dist/emblems/ball/ball.family.seamed.d.ts +31 -0
- package/dist/emblems/ball/ball.family.seamed.js +26 -0
- package/dist/emblems/ball/ball.fieldhockey.d.ts +1 -0
- package/dist/emblems/ball/ball.fieldhockey.js +15 -0
- package/dist/emblems/ball/ball.football.d.ts +3 -0
- package/dist/emblems/ball/ball.football.js +51 -0
- package/dist/emblems/ball/ball.gaelic.d.ts +2 -0
- package/dist/emblems/ball/ball.gaelic.js +30 -0
- package/dist/emblems/ball/ball.golf.d.ts +1 -0
- package/dist/emblems/ball/ball.golf.js +15 -0
- package/dist/emblems/ball/ball.hammer.d.ts +1 -0
- package/dist/emblems/ball/ball.hammer.js +31 -0
- package/dist/emblems/ball/ball.handball.d.ts +1 -0
- package/dist/emblems/ball/ball.handball.js +25 -0
- package/dist/emblems/ball/ball.index.d.ts +48 -0
- package/dist/emblems/ball/ball.index.js +103 -0
- package/dist/emblems/ball/ball.math.d.ts +38 -0
- package/dist/emblems/ball/ball.math.js +105 -0
- package/dist/emblems/ball/ball.object.d.ts +38 -0
- package/dist/emblems/ball/ball.object.js +20 -0
- package/dist/emblems/ball/ball.padel.d.ts +1 -0
- package/dist/emblems/ball/ball.padel.js +13 -0
- package/dist/emblems/ball/ball.pickleball.d.ts +2 -0
- package/dist/emblems/ball/ball.pickleball.js +26 -0
- package/dist/emblems/ball/ball.polyhedra.d.ts +15 -0
- package/dist/emblems/ball/ball.polyhedra.js +63 -0
- package/dist/emblems/ball/ball.puck.d.ts +3 -0
- package/dist/emblems/ball/ball.puck.js +22 -0
- package/dist/emblems/ball/ball.roundnet.d.ts +1 -0
- package/dist/emblems/ball/ball.roundnet.js +15 -0
- package/dist/emblems/ball/ball.rugby.d.ts +1 -0
- package/dist/emblems/ball/ball.rugby.js +35 -0
- package/dist/emblems/ball/ball.sepaktakraw.d.ts +1 -0
- package/dist/emblems/ball/ball.sepaktakraw.js +48 -0
- package/dist/emblems/ball/ball.shuttlecock.d.ts +6 -0
- package/dist/emblems/ball/ball.shuttlecock.js +93 -0
- package/dist/emblems/ball/ball.sliotar.d.ts +1 -0
- package/dist/emblems/ball/ball.sliotar.js +14 -0
- package/dist/emblems/ball/ball.smooth.d.ts +4 -0
- package/dist/emblems/ball/ball.smooth.js +51 -0
- package/dist/emblems/ball/ball.soccer.d.ts +2 -0
- package/dist/emblems/ball/ball.soccer.js +54 -0
- package/dist/emblems/ball/ball.softball.d.ts +1 -0
- package/dist/emblems/ball/ball.softball.js +14 -0
- package/dist/emblems/ball/ball.squash.d.ts +7 -0
- package/dist/emblems/ball/ball.squash.js +27 -0
- package/dist/emblems/ball/ball.stack.d.ts +48 -0
- package/dist/emblems/ball/ball.stack.js +127 -0
- package/dist/emblems/ball/ball.stitch.d.ts +10 -0
- package/dist/emblems/ball/ball.stitch.js +59 -0
- package/dist/emblems/ball/ball.tennis.d.ts +1 -0
- package/dist/emblems/ball/ball.tennis.js +13 -0
- package/dist/emblems/ball/ball.teqball.d.ts +1 -0
- package/dist/emblems/ball/ball.teqball.js +27 -0
- package/dist/emblems/ball/ball.volleyball.d.ts +3 -0
- package/dist/emblems/ball/ball.volleyball.js +56 -0
- package/dist/emblems/ball/ball.waterpolo.d.ts +1 -0
- package/dist/emblems/ball/ball.waterpolo.js +31 -0
- package/dist/emblems/crest/diamond.d.ts +2 -0
- package/dist/emblems/crest/diamond.js +18 -0
- package/dist/emblems/crest/pennant.d.ts +2 -0
- package/dist/emblems/crest/pennant.js +18 -0
- package/dist/emblems/crest/roundel.d.ts +2 -0
- package/dist/emblems/crest/roundel.js +18 -0
- package/dist/emblems/crest/shield.d.ts +2 -0
- package/dist/emblems/crest/shield.js +17 -0
- package/dist/emblems/emblem.api.d.ts +39 -9
- package/dist/emblems/emblem.api.js +38 -10
- package/dist/emblems/emblem.core.d.ts +42 -6
- package/dist/emblems/emblem.core.js +55 -11
- package/dist/emblems/emblem.ids.d.ts +33 -27
- package/dist/emblems/emblem.ids.js +35 -16
- package/dist/emblems/emblem.lathe.d.ts +59 -0
- package/dist/emblems/emblem.lathe.js +404 -0
- package/dist/emblems/emblem.material.d.ts +9 -0
- package/dist/emblems/emblem.material.data.d.ts +34 -0
- package/dist/emblems/emblem.material.data.js +85 -0
- package/dist/emblems/emblem.material.js +23 -0
- package/dist/emblems/emblem.medal.d.ts +6 -0
- package/dist/emblems/emblem.medal.js +38 -0
- package/dist/emblems/emblem.registry.js +142 -4
- package/dist/emblems/emblem.shapes.d.ts +31 -12
- package/dist/emblems/emblem.shapes.js +99 -33
- package/dist/emblems/gear/gear.badmintonracket.d.ts +1 -0
- package/dist/emblems/gear/gear.badmintonracket.js +15 -0
- package/dist/emblems/gear/gear.baseballglove.d.ts +1 -0
- package/dist/emblems/gear/gear.baseballglove.js +15 -0
- package/dist/emblems/gear/gear.core.d.ts +83 -0
- package/dist/emblems/gear/gear.core.js +120 -0
- package/dist/emblems/gear/gear.cricketbat.d.ts +1 -0
- package/dist/emblems/gear/gear.cricketbat.js +15 -0
- package/dist/emblems/gear/gear.field.d.ts +6 -0
- package/dist/emblems/gear/gear.field.js +81 -0
- package/dist/emblems/gear/gear.fieldhockeystick.d.ts +1 -0
- package/dist/emblems/gear/gear.fieldhockeystick.js +15 -0
- package/dist/emblems/gear/gear.footballhelmet.d.ts +1 -0
- package/dist/emblems/gear/gear.footballhelmet.js +15 -0
- package/dist/emblems/gear/gear.goaliemask.d.ts +1 -0
- package/dist/emblems/gear/gear.goaliemask.js +17 -0
- package/dist/emblems/gear/gear.goalnet.d.ts +1 -0
- package/dist/emblems/gear/gear.goalnet.js +15 -0
- package/dist/emblems/gear/gear.hockeystick.d.ts +1 -0
- package/dist/emblems/gear/gear.hockeystick.js +15 -0
- package/dist/emblems/gear/gear.index.d.ts +22 -0
- package/dist/emblems/gear/gear.index.js +45 -0
- package/dist/emblems/gear/gear.lacrossestick.d.ts +1 -0
- package/dist/emblems/gear/gear.lacrossestick.js +15 -0
- package/dist/emblems/gear/gear.rackets.d.ts +4 -0
- package/dist/emblems/gear/gear.rackets.js +60 -0
- package/dist/emblems/gear/gear.skates.d.ts +3 -0
- package/dist/emblems/gear/gear.skates.js +39 -0
- package/dist/emblems/gear/gear.sticks.d.ts +3 -0
- package/dist/emblems/gear/gear.sticks.js +34 -0
- package/dist/emblems/gear/gear.tabletennispaddle.d.ts +1 -0
- package/dist/emblems/gear/gear.tabletennispaddle.js +15 -0
- package/dist/emblems/gear/gear.tennisracket.d.ts +1 -0
- package/dist/emblems/gear/gear.tennisracket.js +15 -0
- package/dist/emblems/gear/gear.track.d.ts +4 -0
- package/dist/emblems/gear/gear.track.js +45 -0
- package/dist/emblems/gear/gear.water.d.ts +2 -0
- package/dist/emblems/gear/gear.water.js +25 -0
- package/dist/emblems/medal/bronze.d.ts +2 -0
- package/dist/emblems/medal/bronze.js +4 -0
- package/dist/emblems/medal/gold.d.ts +2 -0
- package/dist/emblems/medal/gold.js +4 -0
- package/dist/emblems/medal/place-1.d.ts +2 -0
- package/dist/emblems/medal/place-1.js +4 -0
- package/dist/emblems/medal/place-2.d.ts +2 -0
- package/dist/emblems/medal/place-2.js +4 -0
- package/dist/emblems/medal/place-3.d.ts +2 -0
- package/dist/emblems/medal/place-3.js +4 -0
- package/dist/emblems/medal/silver.d.ts +2 -0
- package/dist/emblems/medal/silver.js +4 -0
- package/dist/emblems/sport/afl.d.ts +2 -0
- package/dist/emblems/sport/afl.js +12 -0
- package/dist/emblems/sport/artisticswimming.d.ts +2 -0
- package/dist/emblems/sport/artisticswimming.js +16 -0
- package/dist/emblems/sport/athletics.d.ts +2 -0
- package/dist/emblems/sport/athletics.js +12 -0
- package/dist/emblems/sport/badminton.d.ts +2 -0
- package/dist/emblems/sport/badminton.js +13 -0
- package/dist/emblems/sport/cfl.d.ts +2 -0
- package/dist/emblems/sport/cfl.js +5 -0
- package/dist/emblems/sport/cricket.d.ts +2 -0
- package/dist/emblems/sport/cricket.js +5 -0
- package/dist/emblems/sport/curling.d.ts +2 -0
- package/dist/emblems/sport/curling.js +14 -0
- package/dist/emblems/sport/diving.d.ts +2 -0
- package/dist/emblems/sport/diving.js +18 -0
- package/dist/emblems/sport/fieldhockey.d.ts +2 -0
- package/dist/emblems/sport/fieldhockey.js +11 -0
- package/dist/emblems/sport/gaelic.d.ts +2 -0
- package/dist/emblems/sport/gaelic.js +11 -0
- package/dist/emblems/sport/handball.d.ts +2 -0
- package/dist/emblems/sport/handball.js +5 -0
- package/dist/emblems/sport/ifaf.d.ts +2 -0
- package/dist/emblems/sport/ifaf.js +5 -0
- package/dist/emblems/sport/lacrosse.d.ts +2 -0
- package/dist/emblems/sport/lacrosse.js +13 -0
- package/dist/emblems/sport/mlb.d.ts +2 -0
- package/dist/emblems/sport/mlb.js +5 -0
- package/dist/emblems/sport/nba.d.ts +2 -0
- package/dist/emblems/sport/nba.js +5 -0
- package/dist/emblems/sport/netball.d.ts +2 -0
- package/dist/emblems/sport/netball.js +14 -0
- package/dist/emblems/sport/nfl.d.ts +2 -0
- package/dist/emblems/sport/nfl.js +5 -0
- package/dist/emblems/sport/nhl.d.ts +2 -0
- package/dist/emblems/sport/nhl.js +5 -0
- package/dist/emblems/sport/padel.d.ts +2 -0
- package/dist/emblems/sport/padel.js +14 -0
- package/dist/emblems/sport/pickleball.d.ts +2 -0
- package/dist/emblems/sport/pickleball.js +13 -0
- package/dist/emblems/sport/racquetball.d.ts +2 -0
- package/dist/emblems/sport/racquetball.js +13 -0
- package/dist/emblems/sport/roundnet.d.ts +2 -0
- package/dist/emblems/sport/roundnet.js +15 -0
- package/dist/emblems/sport/rugby.d.ts +2 -0
- package/dist/emblems/sport/rugby.js +5 -0
- package/dist/emblems/sport/sepaktakraw.d.ts +2 -0
- package/dist/emblems/sport/sepaktakraw.js +11 -0
- package/dist/emblems/sport/skating.d.ts +2 -0
- package/dist/emblems/sport/skating.js +14 -0
- package/dist/emblems/sport/soccer.d.ts +2 -0
- package/dist/emblems/sport/soccer.js +5 -0
- package/dist/emblems/sport/squash.d.ts +2 -0
- package/dist/emblems/sport/squash.js +15 -0
- package/dist/emblems/sport/swimming.d.ts +2 -0
- package/dist/emblems/sport/swimming.js +15 -0
- package/dist/emblems/sport/tabletennis.d.ts +2 -0
- package/dist/emblems/sport/tabletennis.js +12 -0
- package/dist/emblems/sport/tennis.d.ts +2 -0
- package/dist/emblems/sport/tennis.js +5 -0
- package/dist/emblems/sport/teqball.d.ts +2 -0
- package/dist/emblems/sport/teqball.js +15 -0
- package/dist/emblems/sport/volleyball.d.ts +2 -0
- package/dist/emblems/sport/volleyball.js +5 -0
- package/dist/emblems/sport/waterpolo.d.ts +2 -0
- package/dist/emblems/sport/waterpolo.js +15 -0
- package/dist/emblems/trophy/baseball.d.ts +2 -0
- package/dist/emblems/trophy/baseball.js +14 -0
- package/dist/emblems/trophy/basketball.d.ts +2 -0
- package/dist/emblems/trophy/basketball.js +16 -0
- package/dist/emblems/trophy/belt.d.ts +2 -0
- package/dist/emblems/trophy/belt.js +16 -0
- package/dist/emblems/trophy/bowl.d.ts +2 -0
- package/dist/emblems/trophy/bowl.js +7 -0
- package/dist/emblems/trophy/canadian-bowl.d.ts +2 -0
- package/dist/emblems/trophy/canadian-bowl.js +22 -0
- package/dist/emblems/trophy/cricket-urn.d.ts +2 -0
- package/dist/emblems/trophy/cricket-urn.js +22 -0
- package/dist/emblems/trophy/cup.d.ts +2 -0
- package/dist/emblems/trophy/cup.js +5 -0
- package/dist/emblems/trophy/football.d.ts +2 -0
- package/dist/emblems/trophy/football.js +10 -0
- package/dist/emblems/trophy/globe.d.ts +2 -0
- package/dist/emblems/trophy/globe.js +8 -0
- package/dist/emblems/trophy/hockey-cup.d.ts +2 -0
- package/dist/emblems/trophy/hockey-cup.js +21 -0
- package/dist/emblems/trophy/laurel.d.ts +2 -0
- package/dist/emblems/trophy/laurel.js +40 -0
- package/dist/emblems/trophy/lidded-cup.d.ts +2 -0
- package/dist/emblems/trophy/lidded-cup.js +20 -0
- package/dist/emblems/trophy/plaque.d.ts +2 -0
- package/dist/emblems/trophy/plaque.js +16 -0
- package/dist/emblems/trophy/rosette.d.ts +2 -0
- package/dist/emblems/trophy/rosette.js +27 -0
- package/dist/emblems/trophy/rugby-cup.d.ts +2 -0
- package/dist/emblems/trophy/rugby-cup.js +22 -0
- package/dist/emblems/trophy/salver.d.ts +2 -0
- package/dist/emblems/trophy/salver.js +8 -0
- package/dist/emblems/trophy/soccer-ball.d.ts +2 -0
- package/dist/emblems/trophy/soccer-ball.js +8 -0
- package/dist/emblems/trophy/soccer-globe.d.ts +2 -0
- package/dist/emblems/trophy/soccer-globe.js +17 -0
- package/dist/emblems/trophy/tennis-cup.d.ts +2 -0
- package/dist/emblems/trophy/tennis-cup.js +23 -0
- package/dist/emblems/trophy/tennis-plate.d.ts +2 -0
- package/dist/emblems/trophy/tennis-plate.js +15 -0
- package/dist/emblems-entry.d.ts +10 -6
- package/dist/emblems-entry.js +3 -2
- package/dist/index.d.ts +114 -1
- package/dist/index.js +116 -3
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +28 -8
- package/LICENSES/CC-BY-3.0.md +0 -15
- package/dist/emblems/ball/soccer.d.ts +0 -2
- package/dist/emblems/ball/soccer.js +0 -9
- package/dist/emblems/emblem.ball.d.ts +0 -28
- package/dist/emblems/emblem.ball.js +0 -70
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Stitches and rows along a curve on the sphere: short marks that cross a seam, spaced evenly along it.
|
|
2
|
+
import { add, cross, dot, mul, norm, sub } from "./ball.math.js";
|
|
3
|
+
/** The point of a closed or open curve at a fraction of its length, and the tangent there. */
|
|
4
|
+
function pointAt(pts, closed, cumulative, total, f) {
|
|
5
|
+
const target = f * total;
|
|
6
|
+
let i = 0;
|
|
7
|
+
while (i < cumulative.length - 2 && cumulative[i + 1] < target)
|
|
8
|
+
i++;
|
|
9
|
+
const a = pts[i], b = pts[(i + 1) % pts.length];
|
|
10
|
+
const span = cumulative[i + 1] - cumulative[i] || 1;
|
|
11
|
+
const k = (target - cumulative[i]) / span;
|
|
12
|
+
const p = norm(add(mul(a, 1 - k), mul(b, k)));
|
|
13
|
+
return { p, t: norm(sub(b, a)) };
|
|
14
|
+
}
|
|
15
|
+
/** Marks across a curve: `count` marks evenly along it; a mark runs `half` radians either side of the seam and leans along it by `lean`. A `v` mark has two legs that meet on the seam (a baseball's stitch). */
|
|
16
|
+
export function stitches(pts, closed, count, half, o) {
|
|
17
|
+
const n = pts.length;
|
|
18
|
+
const cumulative = [0];
|
|
19
|
+
const last = closed ? n : n - 1;
|
|
20
|
+
for (let i = 0; i < last; i++) {
|
|
21
|
+
const a = pts[i], b = pts[(i + 1) % n];
|
|
22
|
+
cumulative.push(cumulative[i] + Math.acos(Math.max(-1, Math.min(1, dot(a, b)))));
|
|
23
|
+
}
|
|
24
|
+
const total = cumulative[cumulative.length - 1];
|
|
25
|
+
const out = [];
|
|
26
|
+
const lean = o?.lean ?? 0;
|
|
27
|
+
const shift = o?.offset ?? 0;
|
|
28
|
+
for (let i = 0; i < count; i++) {
|
|
29
|
+
const f = closed ? (i + (o?.phase ?? 0)) / count : (i + 0.5) / count;
|
|
30
|
+
const { p, t } = pointAt(pts, closed, cumulative, total, f);
|
|
31
|
+
const side = norm(cross(p, t));
|
|
32
|
+
const c = norm(add(p, mul(side, shift)));
|
|
33
|
+
const a = norm(add(add(c, mul(side, half)), mul(t, -lean)));
|
|
34
|
+
const b = norm(add(sub(c, mul(side, half)), mul(t, -lean)));
|
|
35
|
+
if (o?.v === true)
|
|
36
|
+
out.push([a, norm(add(c, mul(t, lean))), b]);
|
|
37
|
+
else
|
|
38
|
+
out.push([a, b]);
|
|
39
|
+
}
|
|
40
|
+
return out;
|
|
41
|
+
}
|
|
42
|
+
/** A dashed row: segments of a curve, each `dash` of every `period` long as a fraction of the curve. */
|
|
43
|
+
export function dashes(pts, closed, count, fill = 0.5) {
|
|
44
|
+
const n = pts.length;
|
|
45
|
+
const out = [];
|
|
46
|
+
const per = n / count;
|
|
47
|
+
for (let i = 0; i < count; i++) {
|
|
48
|
+
const from = i * per;
|
|
49
|
+
const to = from + per * fill;
|
|
50
|
+
const seg = [];
|
|
51
|
+
for (let j = Math.floor(from); j <= Math.ceil(to); j++) {
|
|
52
|
+
const idx = closed ? j % n : Math.min(j, n - 1);
|
|
53
|
+
seg.push(pts[idx]);
|
|
54
|
+
}
|
|
55
|
+
if (seg.length > 1)
|
|
56
|
+
out.push(seg);
|
|
57
|
+
}
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const BALL_TENNIS: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Tennis ball: optic-yellow felt with a white strip of rubber along the seam. The felt's fuzz is the grain.
|
|
2
|
+
import { seamedBall } from "./ball.family.seamed.js";
|
|
3
|
+
export const BALL_TENNIS = /* @__PURE__ */ seamedBall({
|
|
4
|
+
id: "ball:tennis",
|
|
5
|
+
en: "Tennis ball",
|
|
6
|
+
ja: "テニスボール",
|
|
7
|
+
size: { extentMm: 67.0, diameterMm: 67.0, massG: [56.0, 59.4], rule: "ITF Rules of Tennis, Rule 3 The Ball and Appendix I The Ball (a)-(c)" },
|
|
8
|
+
base: "#d3e11f",
|
|
9
|
+
b: 0.33,
|
|
10
|
+
view: { yaw: 25, pitch: 40, roll: 15 },
|
|
11
|
+
mat: { gloss: 0.12, shade: "#3f4a06", grain: { f: 1.8, a: 0.55, seed: 7 } },
|
|
12
|
+
strip: { colour: "#f4f6e4", width: 2.7 },
|
|
13
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const BALL_TEQBALL: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Teqball: the soccer ball's 32 panels in our colours, teal and white, with a pale inset on each hexagon.
|
|
2
|
+
import { defineBall } from "./ball.engine.js";
|
|
3
|
+
import { shrink, truncatedIcosahedron } from "./ball.polyhedra.js";
|
|
4
|
+
import { blend, mix } from "./ball.core.js";
|
|
5
|
+
export const BALL_TEQBALL = /* @__PURE__ */ defineBall({
|
|
6
|
+
id: "ball:teqball",
|
|
7
|
+
en: "Teqball ball",
|
|
8
|
+
ja: "テックボール用ボール",
|
|
9
|
+
size: { extentMm: 216.4, diameterMm: 216.4, circumferenceMm: 680.0, massG: [370, 400], rule: "FITEQ Official Rules and Regulations of Teqball 2026, Rule 3 The Official Ball, 3.1.1-3.1.6", note: "Diameter worked out from the middle of the circumference range." },
|
|
10
|
+
spec: {
|
|
11
|
+
view: { yaw: 30, pitch: 24, roll: 8 },
|
|
12
|
+
base: "#0f9aa8",
|
|
13
|
+
ground: "#f6f8f8",
|
|
14
|
+
mat: { gloss: 0.7, shade: "#0c2a40", grain: { f: 1.1, a: 0.1 } },
|
|
15
|
+
draw: (s, base) => {
|
|
16
|
+
const t = truncatedIcosahedron();
|
|
17
|
+
const inset = blend(base, "#ffffff", 0.82);
|
|
18
|
+
let out = "";
|
|
19
|
+
t.hexagons.forEach((h, i) => (out += s.panel(shrink(h, t.hexagonCentres[i], 0.38), inset, { n: 2 })));
|
|
20
|
+
for (const p of t.pentagons)
|
|
21
|
+
out += s.panel(p, base, { ink: true });
|
|
22
|
+
out += s.strokes(t.edges, mix(base, -0.4), 1.1);
|
|
23
|
+
out += s.strokes(t.edges, "#fff", 0.4, { deco: true, opacity: 0.4, dx: 0.3, dy: 0.35 });
|
|
24
|
+
return out;
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
});
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const BALL_VOLLEYBALL: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
|
|
2
|
+
export declare const BALL_VOLLEYBALL_8: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
|
|
3
|
+
export declare const BALL_BEACH_VOLLEYBALL: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Volleyball: the 18-panel indoor ball in yellow, blue and white, the 8-panel version, and the beach volleyball in its own bright colours. All made of our own layout of curved panels.
|
|
2
|
+
import { defineBall } from "./ball.engine.js";
|
|
3
|
+
import { octants8, strips18 } from "./ball.family.panelled.js";
|
|
4
|
+
const YELLOW = "#f3c81c";
|
|
5
|
+
const BLUE = "#1f5fbf";
|
|
6
|
+
const WHITE = "#f6f4ee";
|
|
7
|
+
export const BALL_VOLLEYBALL = /* @__PURE__ */ defineBall({
|
|
8
|
+
id: "ball:volleyball",
|
|
9
|
+
en: "Volleyball",
|
|
10
|
+
ja: "バレーボール",
|
|
11
|
+
size: { extentMm: 210.1, diameterMm: 210.1, circumferenceMm: 660.0, massG: [260, 280], rule: "FIVB Official Volleyball Rules 2025-2028, Rule 3 Balls, 3.1 Standards", note: "Diameter worked out from the middle of the circumference range." },
|
|
12
|
+
spec: {
|
|
13
|
+
view: { yaw: 28, pitch: 22, roll: 0 },
|
|
14
|
+
base: YELLOW,
|
|
15
|
+
mat: { gloss: 0.75, shade: "#1a2a50", grain: { f: 1.2, a: 0.12 } },
|
|
16
|
+
draw: (s, base) => strips18(s, [
|
|
17
|
+
[base, BLUE],
|
|
18
|
+
[WHITE, BLUE],
|
|
19
|
+
[BLUE, WHITE],
|
|
20
|
+
[base, WHITE],
|
|
21
|
+
[WHITE, base],
|
|
22
|
+
[BLUE, base],
|
|
23
|
+
], "#3a4560"),
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
export const BALL_VOLLEYBALL_8 = /* @__PURE__ */ defineBall({
|
|
27
|
+
id: "ball:volleyball-8",
|
|
28
|
+
en: "Volleyball, 8 panels",
|
|
29
|
+
ja: "バレーボール(8枚貼り)",
|
|
30
|
+
size: { extentMm: 210.1, diameterMm: 210.1, circumferenceMm: 660.0, massG: [260, 280], rule: "FIVB Official Volleyball Rules 2025-2028, Rule 3 Balls, 3.1 Standards", note: "Diameter worked out from the middle of the circumference range." },
|
|
31
|
+
spec: {
|
|
32
|
+
view: { yaw: 32, pitch: 26, roll: 0 },
|
|
33
|
+
base: YELLOW,
|
|
34
|
+
mat: { gloss: 0.75, shade: "#1a2a50", grain: { f: 1.2, a: 0.12 } },
|
|
35
|
+
draw: (s, base) => octants8(s, (sx, sy, sz) => (sy > 0 ? (sx * sz > 0 ? base : BLUE) : sx * sz > 0 ? WHITE : BLUE), "#3a4560"),
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
export const BALL_BEACH_VOLLEYBALL = /* @__PURE__ */ defineBall({
|
|
39
|
+
id: "ball:beach-volleyball",
|
|
40
|
+
en: "Beach volleyball",
|
|
41
|
+
ja: "ビーチバレーボール",
|
|
42
|
+
size: { extentMm: 213.3, diameterMm: 213.3, circumferenceMm: 670.0, massG: [260, 280], rule: "FIVB Official Beach Volleyball Rules 2025-2028, Rule 3 Balls, 3.1 Standards", note: "Diameter worked out from the middle of the circumference range." },
|
|
43
|
+
spec: {
|
|
44
|
+
view: { yaw: 28, pitch: 22, roll: 0 },
|
|
45
|
+
base: "#f2701f",
|
|
46
|
+
mat: { gloss: 0.6, shade: "#4a2410", grain: { f: 1.2, a: 0.1 } },
|
|
47
|
+
draw: (s, base) => strips18(s, [
|
|
48
|
+
[base, WHITE],
|
|
49
|
+
[WHITE, "#14a3d6"],
|
|
50
|
+
[base, "#14a3d6"],
|
|
51
|
+
[WHITE, base],
|
|
52
|
+
[base, WHITE],
|
|
53
|
+
[WHITE, "#14a3d6"],
|
|
54
|
+
], "#7a4a30"),
|
|
55
|
+
},
|
|
56
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const BALL_WATER_POLO: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// Water polo ball: yellow, with deep dark grip channels that follow the seams of its panels. Three seams at right angles cut it into eight panels; beside each seam run a fine groove on each side, which is
|
|
2
|
+
// what the grip of a water polo ball looks like. The rest of the surface is the pebbled grain.
|
|
3
|
+
import { defineBall } from "./ball.engine.js";
|
|
4
|
+
import { greatCircle, smallCircle } from "./ball.math.js";
|
|
5
|
+
import { mix } from "./ball.core.js";
|
|
6
|
+
const AXES = [[1, 0, 0], [0, 1, 0], [0, 0, 1]];
|
|
7
|
+
/** How far the grooves run from a seam, in radians. */
|
|
8
|
+
const OFFSETS = [0.17];
|
|
9
|
+
export const BALL_WATER_POLO = /* @__PURE__ */ defineBall({
|
|
10
|
+
id: "ball:water-polo",
|
|
11
|
+
en: "Water polo ball",
|
|
12
|
+
ja: "水球ボール",
|
|
13
|
+
size: { extentMm: 221.2, diameterMm: 221.2, circumferenceMm: 695.0, massG: [400, 450], rule: "World Aquatics Competition Regulations, Part Six Water Polo Rules, Appendix 4 Field of Play & Equipment, 20.4.3 Ball (20.4.3.1-20.4.3.4); Part Six rule 1.1 points to Appendix 4", note: "Men's ball. Diameter worked out from the middle of the circumference range. Colour is not regulated." },
|
|
14
|
+
spec: {
|
|
15
|
+
view: { yaw: 30, pitch: 24, roll: 0 },
|
|
16
|
+
base: "#f2c012",
|
|
17
|
+
mat: { gloss: 0.5, shade: "#4a2c04", grain: { f: 1.6, a: 0.3 } },
|
|
18
|
+
draw: (s, base) => {
|
|
19
|
+
const channel = mix(base, -0.62);
|
|
20
|
+
let out = "";
|
|
21
|
+
// The grooves beside each seam: a pair on each side of it.
|
|
22
|
+
const grooves = AXES.flatMap((a) => OFFSETS.flatMap((o) => [smallCircle(a, Math.PI / 2 - o, 96), smallCircle(a, Math.PI / 2 + o, 96)]));
|
|
23
|
+
out += s.strokes(grooves, mix(base, -0.5), 1.1, { closed: true, ink: false, opacity: 0.9 });
|
|
24
|
+
// The seams themselves are the wide channels: dark, with the raised lips either side of them.
|
|
25
|
+
const seams = AXES.map((a) => greatCircle(a, 96));
|
|
26
|
+
out += s.strokes(seams, channel, 3.8, { closed: true });
|
|
27
|
+
out += s.strokes(seams, mix(base, 0.35), 0.5, { closed: true, deco: true, opacity: 0.55, dx: 0.6, dy: 0.7 });
|
|
28
|
+
return out;
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// A diamond with a thin diamond inside it, tinted by a team's colours, with the team's letters on it or a star. Drawn for this package.
|
|
2
|
+
import { defineFlat, starPath } from "../emblem.shapes.js";
|
|
3
|
+
/** A diamond with a thin diamond inside it. */
|
|
4
|
+
export const CREST_DIAMOND = /* @__PURE__ */ defineFlat("crest:diamond", "Diamond crest", "ひし形のエンブレム", "ours", {
|
|
5
|
+
metal: "flat",
|
|
6
|
+
color: "#2d5a8c",
|
|
7
|
+
ribbon: "#f4f0e4",
|
|
8
|
+
front: [
|
|
9
|
+
["m", "M32 3L61 32 32 61 3 32z"],
|
|
10
|
+
["r", "M32 9L55 32 32 55 9 32z"],
|
|
11
|
+
["m", "M32 14L50 32 32 50 14 32z"],
|
|
12
|
+
["e", "M32 6L58 32 32 58 6 32z", "1.4"],
|
|
13
|
+
["l", "M32 14L14 32l7 0 11-11z"],
|
|
14
|
+
],
|
|
15
|
+
blank: [["f", starPath(32, 33, 11, 4.6), "#ffffff"]],
|
|
16
|
+
letters: [32, 32, 20],
|
|
17
|
+
rim: 3,
|
|
18
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// A pennant on a pole, tinted by a team's colours, with the team's letters on it or a star. Drawn for this package.
|
|
2
|
+
import { defineFlat, starPath } from "../emblem.shapes.js";
|
|
3
|
+
/** A pennant on a pole. */
|
|
4
|
+
export const CREST_PENNANT = /* @__PURE__ */ defineFlat("crest:pennant", "Pennant crest", "ペナント形のエンブレム", "ours", {
|
|
5
|
+
metal: "flat",
|
|
6
|
+
color: "#2d5a8c",
|
|
7
|
+
ribbon: "#f4f0e4",
|
|
8
|
+
front: [
|
|
9
|
+
["m", "M9 3h4v58H9z"],
|
|
10
|
+
["m", "M13 8L58 32 13 56z"],
|
|
11
|
+
["r", "M13 8L58 32 52 35 13 14z"],
|
|
12
|
+
["e", "M16 12.6L50.4 32 16 51.4z", "1.2"],
|
|
13
|
+
["l", "M16 13l16 8-16 4z"],
|
|
14
|
+
],
|
|
15
|
+
blank: [["f", starPath(28, 33, 9, 3.8), "#ffffff"]],
|
|
16
|
+
letters: [29, 33, 17],
|
|
17
|
+
rim: 3,
|
|
18
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// A round badge with a ring inside its edge, tinted by a team's colours, with the team's letters on it or a star. Drawn for this package.
|
|
2
|
+
import { circlePath, defineFlat, starPath } from "../emblem.shapes.js";
|
|
3
|
+
/** A round badge with a ring inside its edge. */
|
|
4
|
+
export const CREST_ROUNDEL = /* @__PURE__ */ defineFlat("crest:roundel", "Round crest", "丸形のエンブレム", "ours", {
|
|
5
|
+
metal: "flat",
|
|
6
|
+
color: "#2d5a8c",
|
|
7
|
+
ribbon: "#f4f0e4",
|
|
8
|
+
front: [
|
|
9
|
+
["o", circlePath(32, 32, 28)],
|
|
10
|
+
["r", circlePath(32, 32, 23.4)],
|
|
11
|
+
["o", circlePath(32, 32, 20.4)],
|
|
12
|
+
["e", circlePath(32, 32, 26.2), "1.4"],
|
|
13
|
+
["l", "M12 28a21 21 0 0 1 15-15 22 22 0 0 0-10 21z"],
|
|
14
|
+
],
|
|
15
|
+
blank: [["f", starPath(32, 33, 13, 5.4), "#ffffff"]],
|
|
16
|
+
letters: [32, 32, 24],
|
|
17
|
+
rim: 3,
|
|
18
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// A heraldic shield with a band across the top, tinted by a team's colours, with the team's letters on it or a star. Drawn for this package.
|
|
2
|
+
import { defineFlat, starPath } from "../emblem.shapes.js";
|
|
3
|
+
/** A heraldic shield with a band across the top. */
|
|
4
|
+
export const CREST_SHIELD = /* @__PURE__ */ defineFlat("crest:shield", "Shield crest", "盾形のエンブレム", "ours", {
|
|
5
|
+
metal: "flat",
|
|
6
|
+
color: "#2d5a8c",
|
|
7
|
+
ribbon: "#f4f0e4",
|
|
8
|
+
front: [
|
|
9
|
+
["m", "M9 5h46v23c0 15-10 24-23 30C19 52 9 43 9 28z"],
|
|
10
|
+
["r", "M9 5h46v9H9z"],
|
|
11
|
+
["e", "M12.5 8.5h39v19.5c0 12.5-8.3 20.6-19.5 26C21.8 48.6 12.5 40.5 12.5 28z", "1.4"],
|
|
12
|
+
["l", "M13 16h10L13 30z"],
|
|
13
|
+
],
|
|
14
|
+
blank: [["f", starPath(32, 34, 12, 5), "#ffffff"]],
|
|
15
|
+
letters: [32, 37, 24],
|
|
16
|
+
rim: 3,
|
|
17
|
+
});
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import type { Emblem, EmblemOptions, EmblemStyle, FrameOptions } from "./emblem.core.ts";
|
|
2
|
-
import { type BallId, type EmblemId } from "./emblem.ids.ts";
|
|
3
|
-
|
|
1
|
+
import type { Emblem, EmblemOptions, EmblemStyle, EmblemTheme, FrameOptions } from "./emblem.core.ts";
|
|
2
|
+
import { type BallId, type CrestShape, type EmblemId, type MedalKind, type SportName } from "./emblem.ids.ts";
|
|
3
|
+
import type { PieceSize } from "./ball/ball.core.ts";
|
|
4
|
+
/** What can name an emblem: an id, a short name (`"cup"` for `"trophy:cup"`), either with a style (`"trophy:cup/line"`), or the emblem itself. */
|
|
4
5
|
export type EmblemRef = EmblemId | `${EmblemId}/${EmblemStyle}` | (string & {}) | Emblem;
|
|
5
|
-
/** The id and style a string names, or `undefined` when it is not an emblem. An id may end in `/metal`, `/line` or `/color
|
|
6
|
+
/** The id and style a string names, or `undefined` when it is not an emblem. An id may end in `/metal`, `/line` or `/color`, and a trophy or an award may be written without its group (`cup`, `crown`). */
|
|
6
7
|
export declare function parseEmblem(value: unknown): {
|
|
7
8
|
id: EmblemId;
|
|
8
9
|
style: EmblemStyle | undefined;
|
|
9
10
|
} | undefined;
|
|
10
|
-
/** True when the value is the id of an emblem (with no style). */
|
|
11
|
+
/** True when the value is the id of an emblem (not a short name, and with no style). */
|
|
11
12
|
export declare function isEmblemId(value: unknown): value is EmblemId;
|
|
12
13
|
/** The emblem a reference names. An unknown name is an error that says what an id looks like. */
|
|
13
14
|
export declare function emblemOf(ref: EmblemRef): {
|
|
@@ -20,8 +21,8 @@ export declare function emblemOf(ref: EmblemRef): {
|
|
|
20
21
|
* @example
|
|
21
22
|
* ```ts
|
|
22
23
|
* import { renderEmblem } from "@johnmorrisdotca/dougu-sports/emblems";
|
|
23
|
-
* const svg = renderEmblem("
|
|
24
|
-
* console.log(svg.startsWith("<svg"), svg.includes("<title>
|
|
24
|
+
* const svg = renderEmblem("trophy:cup", { style: "line", size: 32 });
|
|
25
|
+
* console.log(svg.startsWith("<svg"), svg.includes("<title>Cup</title>"));
|
|
25
26
|
* // true true
|
|
26
27
|
* ```
|
|
27
28
|
*/
|
|
@@ -29,11 +30,11 @@ export declare function renderEmblem(ref: EmblemRef, options?: EmblemOptions): s
|
|
|
29
30
|
/** The same as `renderEmblem`. */
|
|
30
31
|
export declare const emblemSvg: typeof renderEmblem;
|
|
31
32
|
/**
|
|
32
|
-
* An emblem turned: `yaw` degrees about its vertical axis and `pitch` degrees of tilt, from its resting view, in plain SVG. A
|
|
33
|
+
* An emblem turned: `yaw` degrees about its vertical axis and `pitch` degrees of tilt, from its resting view, in plain SVG. A cup, bowl or urn keeps its outline and moves its light, handles and seams; a medal flips like a coin and shows its back; a ball rolls; an icon is not turned.
|
|
33
34
|
* @example
|
|
34
35
|
* ```ts
|
|
35
36
|
* import { emblemFrame, renderEmblem } from "@johnmorrisdotca/dougu-sports/turn";
|
|
36
|
-
* console.log(emblemFrame("
|
|
37
|
+
* console.log(emblemFrame("medal:gold", { yaw: 0 }) === renderEmblem("medal:gold"));
|
|
37
38
|
* // true
|
|
38
39
|
* ```
|
|
39
40
|
*/
|
|
@@ -51,6 +52,8 @@ export interface EmblemInfo {
|
|
|
51
52
|
ja: string;
|
|
52
53
|
source: Emblem["source"];
|
|
53
54
|
kind: Emblem["kind"];
|
|
55
|
+
/** A ball's or an implement's official size, with the rule it is from, where the rulebook gives one. */
|
|
56
|
+
size?: PieceSize;
|
|
54
57
|
}
|
|
55
58
|
/** The names, source and kind of an emblem. */
|
|
56
59
|
export declare function emblemInfo(id: EmblemId): EmblemInfo;
|
|
@@ -58,3 +61,30 @@ export declare function emblemInfo(id: EmblemId): EmblemInfo;
|
|
|
58
61
|
export declare function emblemName(id: EmblemId, language?: "en" | "ja"): string;
|
|
59
62
|
/** The data an emblem is drawn from: a flat emblem's shapes or a ball's marks, for a view that turns it itself. */
|
|
60
63
|
export declare function emblemModel(id: EmblemId): unknown;
|
|
64
|
+
/** What `crest` takes. */
|
|
65
|
+
export interface CrestOptions {
|
|
66
|
+
/** `shield` (the default), `roundel`, `diamond` or `pennant`. */
|
|
67
|
+
shape?: CrestShape;
|
|
68
|
+
/** The team's colour, or its colour and a second colour for the band and the ring. Hex colours or `rgb()`. */
|
|
69
|
+
colors?: string | readonly [string, string?];
|
|
70
|
+
/** Up to three letters. A crest with none has a star. */
|
|
71
|
+
initials?: string;
|
|
72
|
+
size?: number;
|
|
73
|
+
style?: EmblemStyle;
|
|
74
|
+
theme?: EmblemTheme;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* A generic crest tinted by a team's colours, with its letters if it has any: what a team with no logo gets. The letters are in the ink that reads on the colour.
|
|
78
|
+
* @example
|
|
79
|
+
* ```ts
|
|
80
|
+
* import { crest } from "@johnmorrisdotca/dougu-sports/emblems";
|
|
81
|
+
* const svg = crest({ shape: "shield", colors: ["#c8102e", "#f4f0e4"], initials: "NO" });
|
|
82
|
+
* console.log(svg.includes(">NO<"));
|
|
83
|
+
* // true
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
export declare function crest(options?: CrestOptions): string;
|
|
87
|
+
/** A medal on a ribbon: `medal("gold")`, `"silver"` or `"bronze"`; any other kind is the gold one. */
|
|
88
|
+
export declare function medal(kind: MedalKind, options?: EmblemOptions): string;
|
|
89
|
+
/** The icon of a sport, by the names of `SPORT_NAMES`: `sportIcon("nhl")`. An unknown sport is an error. */
|
|
90
|
+
export declare function sportIcon(sport: SportName, options?: EmblemOptions): string;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { EMBLEM_STYLES } from "./emblem.core.js";
|
|
2
|
-
import { BALL_IDS, EMBLEM_IDS } from "./emblem.ids.js";
|
|
2
|
+
import { BALL_IDS, CREST_SHAPES, EMBLEM_ALIASES, EMBLEM_IDS } from "./emblem.ids.js";
|
|
3
3
|
import { EMBLEM_TABLE } from "./emblem.registry.js";
|
|
4
|
-
/** The id and style a string names, or `undefined` when it is not an emblem. An id may end in `/metal`, `/line` or `/color
|
|
4
|
+
/** The id and style a string names, or `undefined` when it is not an emblem. An id may end in `/metal`, `/line` or `/color`, and a trophy or an award may be written without its group (`cup`, `crown`). */
|
|
5
5
|
export function parseEmblem(value) {
|
|
6
6
|
if (typeof value !== "string")
|
|
7
7
|
return undefined;
|
|
@@ -17,9 +17,10 @@ export function parseEmblem(value) {
|
|
|
17
17
|
style = tail;
|
|
18
18
|
text = text.slice(0, slash);
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
const id = Object.hasOwn(EMBLEM_ALIASES, text) ? EMBLEM_ALIASES[text] : text;
|
|
21
|
+
return Object.hasOwn(EMBLEM_TABLE, id) ? { id: id, style } : undefined;
|
|
21
22
|
}
|
|
22
|
-
/** True when the value is the id of an emblem (with no style). */
|
|
23
|
+
/** True when the value is the id of an emblem (not a short name, and with no style). */
|
|
23
24
|
export function isEmblemId(value) {
|
|
24
25
|
return typeof value === "string" && Object.hasOwn(EMBLEM_TABLE, value);
|
|
25
26
|
}
|
|
@@ -29,7 +30,7 @@ export function emblemOf(ref) {
|
|
|
29
30
|
return { emblem: ref, style: undefined };
|
|
30
31
|
const parsed = parseEmblem(ref);
|
|
31
32
|
if (parsed === undefined)
|
|
32
|
-
throw new Error(`Unknown emblem "${ref.slice(0, 60)}". Ids look like "
|
|
33
|
+
throw new Error(`Unknown emblem "${ref.slice(0, 60)}". Ids look like "trophy:cup", "medal:gold", "sport:nhl" or "crest:shield"; see EMBLEM_IDS.`);
|
|
33
34
|
return { emblem: EMBLEM_TABLE[parsed.id], style: parsed.style };
|
|
34
35
|
}
|
|
35
36
|
const withStyle = (style, options) => (style === undefined || options?.style !== undefined ? options : { ...options, style });
|
|
@@ -39,8 +40,8 @@ const withStyle = (style, options) => (style === undefined || options?.style !==
|
|
|
39
40
|
* @example
|
|
40
41
|
* ```ts
|
|
41
42
|
* import { renderEmblem } from "@johnmorrisdotca/dougu-sports/emblems";
|
|
42
|
-
* const svg = renderEmblem("
|
|
43
|
-
* console.log(svg.startsWith("<svg"), svg.includes("<title>
|
|
43
|
+
* const svg = renderEmblem("trophy:cup", { style: "line", size: 32 });
|
|
44
|
+
* console.log(svg.startsWith("<svg"), svg.includes("<title>Cup</title>"));
|
|
44
45
|
* // true true
|
|
45
46
|
* ```
|
|
46
47
|
*/
|
|
@@ -51,11 +52,11 @@ export function renderEmblem(ref, options) {
|
|
|
51
52
|
/** The same as `renderEmblem`. */
|
|
52
53
|
export const emblemSvg = renderEmblem;
|
|
53
54
|
/**
|
|
54
|
-
* An emblem turned: `yaw` degrees about its vertical axis and `pitch` degrees of tilt, from its resting view, in plain SVG. A
|
|
55
|
+
* An emblem turned: `yaw` degrees about its vertical axis and `pitch` degrees of tilt, from its resting view, in plain SVG. A cup, bowl or urn keeps its outline and moves its light, handles and seams; a medal flips like a coin and shows its back; a ball rolls; an icon is not turned.
|
|
55
56
|
* @example
|
|
56
57
|
* ```ts
|
|
57
58
|
* import { emblemFrame, renderEmblem } from "@johnmorrisdotca/dougu-sports/turn";
|
|
58
|
-
* console.log(emblemFrame("
|
|
59
|
+
* console.log(emblemFrame("medal:gold", { yaw: 0 }) === renderEmblem("medal:gold"));
|
|
59
60
|
* // true
|
|
60
61
|
* ```
|
|
61
62
|
*/
|
|
@@ -76,7 +77,8 @@ export const EMBLEMS = Object.freeze(Object.fromEntries(EMBLEM_IDS.map((id) => [
|
|
|
76
77
|
/** The names, source and kind of an emblem. */
|
|
77
78
|
export function emblemInfo(id) {
|
|
78
79
|
const e = EMBLEM_TABLE[id];
|
|
79
|
-
|
|
80
|
+
const size = e.size;
|
|
81
|
+
return size === undefined ? { id, en: e.en, ja: e.ja, source: e.source, kind: e.kind } : { id, en: e.en, ja: e.ja, source: e.source, kind: e.kind, size };
|
|
80
82
|
}
|
|
81
83
|
/** An emblem's name in a language. */
|
|
82
84
|
export function emblemName(id, language = "en") {
|
|
@@ -86,3 +88,29 @@ export function emblemName(id, language = "en") {
|
|
|
86
88
|
export function emblemModel(id) {
|
|
87
89
|
return EMBLEM_TABLE[id].model;
|
|
88
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* A generic crest tinted by a team's colours, with its letters if it has any: what a team with no logo gets. The letters are in the ink that reads on the colour.
|
|
93
|
+
* @example
|
|
94
|
+
* ```ts
|
|
95
|
+
* import { crest } from "@johnmorrisdotca/dougu-sports/emblems";
|
|
96
|
+
* const svg = crest({ shape: "shield", colors: ["#c8102e", "#f4f0e4"], initials: "NO" });
|
|
97
|
+
* console.log(svg.includes(">NO<"));
|
|
98
|
+
* // true
|
|
99
|
+
* ```
|
|
100
|
+
*/
|
|
101
|
+
export function crest(options = {}) {
|
|
102
|
+
const colors = typeof options.colors === "string" ? [options.colors] : (options.colors ?? []);
|
|
103
|
+
const shape = CREST_SHAPES.includes(options.shape) ? options.shape : "shield";
|
|
104
|
+
return EMBLEM_TABLE[`crest:${shape}`].svg({ tint: colors[0], accent: colors[1], initials: options.initials, size: options.size, style: options.style, theme: options.theme });
|
|
105
|
+
}
|
|
106
|
+
/** A medal on a ribbon: `medal("gold")`, `"silver"` or `"bronze"`; any other kind is the gold one. */
|
|
107
|
+
export function medal(kind, options) {
|
|
108
|
+
return (EMBLEM_TABLE[`medal:${kind}`] ?? EMBLEM_TABLE["medal:gold"]).svg(options);
|
|
109
|
+
}
|
|
110
|
+
/** The icon of a sport, by the names of `SPORT_NAMES`: `sportIcon("nhl")`. An unknown sport is an error. */
|
|
111
|
+
export function sportIcon(sport, options) {
|
|
112
|
+
const e = Object.hasOwn(EMBLEM_TABLE, `sport:${sport}`) ? EMBLEM_TABLE[`sport:${sport}`] : undefined;
|
|
113
|
+
if (e === undefined)
|
|
114
|
+
throw new Error(`Unknown sport "${String(sport).slice(0, 40)}": the icons are for the names in SPORT_NAMES.`);
|
|
115
|
+
return e.svg(options);
|
|
116
|
+
}
|
|
@@ -15,11 +15,19 @@ export interface EmblemOptions {
|
|
|
15
15
|
tint?: string;
|
|
16
16
|
/** `inherit` (the default), `auto`, `light` or `dark`. */
|
|
17
17
|
theme?: EmblemTheme;
|
|
18
|
+
/** A second colour: a medal's ribbon, a crest's band, the flags of a trophy. A hex colour or `rgb()`; anything else is ignored. */
|
|
19
|
+
accent?: string;
|
|
20
|
+
/** The letters of a crest, up to three. */
|
|
21
|
+
initials?: string;
|
|
22
|
+
/** A ball: force the grain of its surface on or off. By default it is on for a ball of 48 pixels or more that is not turning. */
|
|
23
|
+
grain?: boolean;
|
|
18
24
|
}
|
|
19
25
|
/** A turn, in degrees from the resting view (0 and 0 is the still drawing): `yaw` about the vertical axis, `pitch` the tilt toward the eye. */
|
|
20
26
|
export interface FrameOptions extends EmblemOptions {
|
|
21
27
|
yaw?: number;
|
|
22
28
|
pitch?: number;
|
|
29
|
+
/** A ball: the turn about the line of sight. */
|
|
30
|
+
roll?: number;
|
|
23
31
|
}
|
|
24
32
|
/** The ink of a drawing when a theme sets it, and the page it is made to read on. */
|
|
25
33
|
export declare const EMBLEM_INK: {
|
|
@@ -36,11 +44,12 @@ export declare const METALS: {
|
|
|
36
44
|
readonly silver: "#aeb6c0";
|
|
37
45
|
readonly bronze: "#b8733a";
|
|
38
46
|
};
|
|
39
|
-
|
|
47
|
+
/** A metal by name, or `flat` for a colour that is no metal (a crest's blue, a sport's plain ink). */
|
|
48
|
+
export type Metal = keyof typeof METALS | "flat";
|
|
40
49
|
/** Where an emblem's art comes from: drawn for this package (`ours`) or taken from a source listed in NOTICE.md. */
|
|
41
|
-
export type EmblemSource = "ours" | "material" | "noto" | "mdi" | "
|
|
42
|
-
/** What an emblem is: a flat object (a front and a back, to flip), a ball (
|
|
43
|
-
export type EmblemKind = "flat" | "ball" | "lathe" | "icon";
|
|
50
|
+
export type EmblemSource = "ours" | "material" | "generated" | "drawn" | "noto" | "mdi" | "commons" | "gameicons";
|
|
51
|
+
/** What an emblem is: a flat object (a front and a back, to flip), a ball (a sphere or a solid, turned in 3D), a body of revolution (`lathe`), an icon (one drawing, not turned) or a piece of gear (a flat drawing, not turned). */
|
|
52
|
+
export type EmblemKind = "flat" | "ball" | "lathe" | "icon" | "gear";
|
|
44
53
|
export type Rgb = readonly [number, number, number];
|
|
45
54
|
/** A colour from `#rgb`, `#rrggbb` or `rgb(r, g, b)`, or `undefined` for anything else. */
|
|
46
55
|
export declare function readColour(value: string | undefined): Rgb | undefined;
|
|
@@ -57,10 +66,16 @@ export interface Resolved {
|
|
|
57
66
|
size: number;
|
|
58
67
|
theme: EmblemTheme;
|
|
59
68
|
tint: Rgb | undefined;
|
|
69
|
+
accent: string | undefined;
|
|
70
|
+
initials: string;
|
|
60
71
|
}
|
|
61
72
|
export declare function resolve(o: EmblemOptions | undefined): Resolved;
|
|
62
73
|
/** The main colour of a metal, or the tint when there is one. */
|
|
63
74
|
export declare const mainOf: (metal: Metal, tint: Rgb | undefined) => Rgb;
|
|
75
|
+
/** The relative luminance of a colour, 0 to 1. */
|
|
76
|
+
export declare function lum(rgb: Rgb): number;
|
|
77
|
+
/** Black or white, whichever reads better on a colour. */
|
|
78
|
+
export declare const onColour: (rgb: Rgb) => string;
|
|
64
79
|
/** A turn in degrees, as a finite number (0 for anything else). */
|
|
65
80
|
export declare const degrees: (value: number | undefined) => number;
|
|
66
81
|
/** The colours a drawing is painted with. In the `line` style every fill is `none`. */
|
|
@@ -74,8 +89,27 @@ export interface Paint {
|
|
|
74
89
|
/** The definitions the fills refer to. */
|
|
75
90
|
defs: string;
|
|
76
91
|
}
|
|
77
|
-
/** The paint
|
|
78
|
-
export declare function paintFor(style: EmblemStyle, main: Rgb
|
|
92
|
+
/** The paint of a ball: a radial gradient in the metal style. The gradient's id names the colour, so two of one colour in a page agree. */
|
|
93
|
+
export declare function paintFor(style: EmblemStyle, main: Rgb): Paint;
|
|
94
|
+
/** A gradient: its id, its definition (a fragment for a `<defs>`) and the fill that names it. */
|
|
95
|
+
export interface Gradient {
|
|
96
|
+
id: string;
|
|
97
|
+
def: string;
|
|
98
|
+
fill: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The shading of a round metal body: a dark edge, a bright band left of the middle, the metal, a darker side, and a faint light from the rim on the far edge, as polished metal throws it. `shift` slides the bright
|
|
102
|
+
* band (a turn). The id names the colour and the shift, so two bodies of one colour in a page share one definition.
|
|
103
|
+
*/
|
|
104
|
+
export declare function cylinderGradient(main: Rgb, shift?: number): Gradient;
|
|
105
|
+
/** The shading of a round flat or a ball: light from the top left, the metal, then dark at the far edge. */
|
|
106
|
+
export declare function orbGradient(main: Rgb): Gradient;
|
|
107
|
+
/** The shading of a flat sheet of metal, from a bright corner to a dark one. */
|
|
108
|
+
export declare function sheetGradient(main: Rgb): Gradient;
|
|
109
|
+
/** The shading of a raised rim: bright on the top left, dark on the bottom right, as a bevel catches the light (or the other way round, for a groove). */
|
|
110
|
+
export declare function bevelGradient(main: Rgb, groove?: boolean): Gradient;
|
|
111
|
+
/** The gradients' definitions as one `<defs>`, with none twice. */
|
|
112
|
+
export declare const defsOf: (gradients: readonly Gradient[]) => string;
|
|
79
113
|
/** A drawing wrapped into a document: the title, the outline's colour for the theme, and the group that strokes it. */
|
|
80
114
|
export declare function wrap(o: {
|
|
81
115
|
title: string;
|
|
@@ -85,6 +119,8 @@ export declare function wrap(o: {
|
|
|
85
119
|
defs?: string;
|
|
86
120
|
body: string;
|
|
87
121
|
box?: string;
|
|
122
|
+
edge?: string;
|
|
123
|
+
width?: number;
|
|
88
124
|
}): string;
|
|
89
125
|
/** One emblem: its id and names, where its art comes from, and the functions that draw it. Importing one of these pulls in its own module and the small renderer it needs, not the other emblems. */
|
|
90
126
|
export interface Emblem<Model = unknown> {
|