@johnmorrisdotca/dougu-sports 0.4.0 → 0.5.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 +29 -1
- package/NOTICE.md +6 -4
- package/README.md +6 -5
- package/dist/emblems/ball/ball.baseball.vintage.d.ts +10 -0
- package/dist/emblems/ball/ball.baseball.vintage.js +70 -0
- package/dist/emblems/ball/ball.core.d.ts +8 -1
- package/dist/emblems/ball/ball.core.js +11 -1
- package/dist/emblems/ball/ball.decal.d.ts +56 -0
- package/dist/emblems/ball/ball.decal.js +146 -0
- package/dist/emblems/ball/ball.engine.d.ts +7 -1
- package/dist/emblems/ball/ball.engine.js +10 -2
- package/dist/emblems/ball/ball.face.d.ts +14 -9
- package/dist/emblems/ball/ball.face.js +6 -5
- package/dist/emblems/ball/ball.family.panelled.d.ts +5 -0
- package/dist/emblems/ball/ball.family.panelled.js +12 -5
- package/dist/emblems/ball/ball.family.seamed.d.ts +8 -1
- package/dist/emblems/ball/ball.family.seamed.js +13 -3
- package/dist/emblems/ball/ball.index.js +6 -1
- package/dist/emblems/ball/ball.puck.print.js +1 -1
- package/dist/emblems/ball/ball.soccer.era.d.ts +23 -0
- package/dist/emblems/ball/ball.soccer.era.js +302 -0
- package/dist/emblems/ball/ball.soccer.store.d.ts +19 -0
- package/dist/emblems/ball/ball.soccer.store.js +176 -0
- package/dist/emblems/ball/ball.soccer.vintage.d.ts +11 -0
- package/dist/emblems/ball/ball.soccer.vintage.js +135 -0
- package/dist/emblems/ball/ball.tilings.d.ts +26 -0
- package/dist/emblems/ball/ball.tilings.js +87 -0
- package/dist/emblems/ball/ball.volleyball.flag.d.ts +12 -0
- package/dist/emblems/ball/ball.volleyball.flag.js +36 -0
- package/dist/emblems/emblem.core.d.ts +6 -2
- package/dist/emblems/emblem.descriptions.js +50 -0
- package/dist/emblems/emblem.ids.d.ts +2 -2
- package/dist/emblems/emblem.ids.js +3 -2
- package/dist/emblems-entry.d.ts +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
// Generic patterns of the kind a sports shop has on its wall, each in three colourways: stars, hexagon outlines, flames, chevrons, a two-tone swirl and a metallic glossy finish. Every pattern is our own
|
|
2
|
+
// drawing on a construction of the family (the 32 panels, or gores that run from pole to pole), and the balls are the size of an 11-a-side ball (IFAB Law 2). No logo, no brand, no team.
|
|
3
|
+
import { defineBall } from "./ball.engine.js";
|
|
4
|
+
import { mix } from "./ball.core.js";
|
|
5
|
+
import { frameAt, place, spiral, star, tongue, turned } from "./ball.decal.js";
|
|
6
|
+
import { shrink, truncatedIcosahedron } from "./ball.polyhedra.js";
|
|
7
|
+
import { gorePoint, gores } from "./ball.tilings.js";
|
|
8
|
+
import { SOCCER_SIZE } from "./ball.soccer.size.js";
|
|
9
|
+
const VIEW = { yaw: 30, pitch: 24, roll: 8 };
|
|
10
|
+
const GLOSS = { gloss: 0.8, shade: "#2a3450", grain: { f: 1.1, a: 0.16 } };
|
|
11
|
+
const lit = (s, seams, width = 0.45) => s.strokes(seams, "#fff", width, { deco: true, opacity: 0.45, dx: 0.3, dy: 0.35 });
|
|
12
|
+
const ball = (id, en, ja, spec) => defineBall({ id, en, ja, size: SOCCER_SIZE, spec });
|
|
13
|
+
// Stars: a five-pointed star on every panel, on a white or a night-blue ground.
|
|
14
|
+
const stars = (w) => ({
|
|
15
|
+
view: VIEW,
|
|
16
|
+
base: w.main,
|
|
17
|
+
ground: w.ground,
|
|
18
|
+
mat: GLOSS,
|
|
19
|
+
draw(s, base, accent) {
|
|
20
|
+
const t = truncatedIcosahedron();
|
|
21
|
+
const dark = accent ?? w.dark;
|
|
22
|
+
let out = "";
|
|
23
|
+
for (const p of t.pentagons)
|
|
24
|
+
out += s.panel(p, dark, { ink: true });
|
|
25
|
+
const big = star(5, 0.2, 0.09);
|
|
26
|
+
const small = star(5, 0.12, 0.054);
|
|
27
|
+
out += s.panels([
|
|
28
|
+
...t.hexagonCentres.map((c, i) => place(frameAt(c, t.hexagonPentagonSides[i][0]), turned(big, 0.35))),
|
|
29
|
+
...t.pentagonCentres.map((c, i) => place(frameAt(c, t.pentagons[i][0]), small)),
|
|
30
|
+
], base, { n: 1 });
|
|
31
|
+
out += s.strokes(t.edges, mix(dark, 0.2), 1.05);
|
|
32
|
+
return out + lit(s, t.edges);
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
// Hexagon outlines: two outlines inside each hexagon, one inside the other, like a honeycomb; the pentagons are solid.
|
|
36
|
+
const hexagons = (w) => ({
|
|
37
|
+
view: VIEW,
|
|
38
|
+
base: w.main,
|
|
39
|
+
ground: w.ground,
|
|
40
|
+
mat: GLOSS,
|
|
41
|
+
draw(s, base, accent) {
|
|
42
|
+
const t = truncatedIcosahedron();
|
|
43
|
+
const dark = accent ?? w.dark;
|
|
44
|
+
let out = "";
|
|
45
|
+
for (const p of t.pentagons)
|
|
46
|
+
out += s.panel(p, dark, { ink: true });
|
|
47
|
+
t.hexagons.forEach((h, i) => {
|
|
48
|
+
out += s.strokes([shrink(h, t.hexagonCentres[i], 0.28), shrink(h, t.hexagonCentres[i], 0.58)], base, 1.1, { closed: true });
|
|
49
|
+
});
|
|
50
|
+
out += s.strokes(t.edges, mix(dark, 0.2), 1.1);
|
|
51
|
+
return out + lit(s, t.edges);
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
// Flames: five tongues of flame leave each dark pentagon, an outer one and a lighter inner one.
|
|
55
|
+
const flames = (w, inner) => ({
|
|
56
|
+
view: VIEW,
|
|
57
|
+
base: w.main,
|
|
58
|
+
ground: w.ground,
|
|
59
|
+
mat: GLOSS,
|
|
60
|
+
draw(s, base, accent) {
|
|
61
|
+
const t = truncatedIcosahedron();
|
|
62
|
+
const core = accent ?? inner;
|
|
63
|
+
let out = "";
|
|
64
|
+
for (const p of t.pentagons)
|
|
65
|
+
out += s.panel(p, w.dark, { ink: true });
|
|
66
|
+
const flame = (r0, r1, a, wd) => tongue(spiral(r0, r1, a, 0.75), (u) => wd * Math.min(1, u * 6 + 0.3) * (1 - u) ** 0.75, 3);
|
|
67
|
+
const frames = t.pentagonCentres.map((c, i) => frameAt(c, t.pentagons[i][0]));
|
|
68
|
+
const rings = (r0, r1, da, wd) => frames.flatMap((f) => [0, 1, 2, 3, 4].map((k) => place(f, flame(r0, r1, Math.PI / 5 + (2 * Math.PI * k) / 5 + da, wd))));
|
|
69
|
+
out += s.panels(rings(0.19, 0.64, -0.1, 0.125), base, { n: 1 });
|
|
70
|
+
out += s.panels(rings(0.21, 0.45, -0.03, 0.06), core, { n: 1 });
|
|
71
|
+
return out + s.strokes(t.edges, mix(w.dark, 0.5), 1);
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
// Chevrons: eight gores from pole to pole, every other one coloured, crossed by three bands that bend into a V on each gore, so that round the ball they make a zigzag.
|
|
75
|
+
const chevrons = (w) => ({
|
|
76
|
+
view: { yaw: 24, pitch: 24, roll: 0 },
|
|
77
|
+
base: w.main,
|
|
78
|
+
ground: w.ground,
|
|
79
|
+
mat: GLOSS,
|
|
80
|
+
draw(s, base, accent) {
|
|
81
|
+
const dark = accent ?? w.dark;
|
|
82
|
+
const tilt = [0, 22, 0];
|
|
83
|
+
const g = gores(8, 0, tilt);
|
|
84
|
+
const at = gorePoint(8, 0, tilt);
|
|
85
|
+
let out = "";
|
|
86
|
+
for (let i = 0; i < 8; i += 2)
|
|
87
|
+
out += s.panel(g.panels[i], base, { n: 1 });
|
|
88
|
+
for (let i = 0; i < 8; i++) {
|
|
89
|
+
for (const s0 of [-0.28, 0.02, 0.32]) {
|
|
90
|
+
const upper = [], lower = [];
|
|
91
|
+
for (let j = 0; j <= 4; j++) {
|
|
92
|
+
const u = j / 4;
|
|
93
|
+
const dip = 0.34 * Math.abs(u - 0.5);
|
|
94
|
+
upper.push(at(i, u, s0 + 0.12 + dip));
|
|
95
|
+
lower.push(at(i, u, s0 + dip));
|
|
96
|
+
}
|
|
97
|
+
const band = [...lower, ...upper.reverse()];
|
|
98
|
+
out += s.panel(band, dark, { n: 2 });
|
|
99
|
+
if (s.line)
|
|
100
|
+
out += s.strokes([band], dark, 0.6, { closed: true });
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
out += s.strokes(g.seams, mix(dark, 0.3), 0.7);
|
|
104
|
+
return out + lit(s, g.seams, 0.4);
|
|
105
|
+
},
|
|
106
|
+
});
|
|
107
|
+
// Swirl: four gores that twist round the ball, two of them in one colour and two in the other.
|
|
108
|
+
const swirl = (w) => ({
|
|
109
|
+
view: { yaw: 20, pitch: 24, roll: 0 },
|
|
110
|
+
base: w.main,
|
|
111
|
+
ground: w.ground,
|
|
112
|
+
mat: { gloss: 0.9, shade: "#2a3450", grain: { f: 0.8, a: 0.08 } },
|
|
113
|
+
draw(s, base) {
|
|
114
|
+
const g = gores(4, 330, [0, 24, 0], 24, 6);
|
|
115
|
+
let out = "";
|
|
116
|
+
for (const { ring, gore } of g.pieces) {
|
|
117
|
+
if (gore % 2 === 1)
|
|
118
|
+
continue;
|
|
119
|
+
out += s.panel(ring, base, { n: 4, ink: true });
|
|
120
|
+
out += s.strokes([ring], base, 0.5, { closed: true, deco: true });
|
|
121
|
+
}
|
|
122
|
+
out += s.strokes(g.seams, mix(w.dark, 0.2), 0.9);
|
|
123
|
+
return out + lit(s, g.seams, 0.5);
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
// Metallic: the 32 panels in a polished finish that mirrors the sky above and the ground below, a light metal on the hexagons and a dark one on the pentagons.
|
|
127
|
+
const metallic = (w) => ({
|
|
128
|
+
view: VIEW,
|
|
129
|
+
base: w.dark,
|
|
130
|
+
ground: w.main,
|
|
131
|
+
mat: { gloss: 1, metal: true, shade: mix(w.dark, -0.4), rim: 0.8 },
|
|
132
|
+
draw(s, base) {
|
|
133
|
+
const t = truncatedIcosahedron();
|
|
134
|
+
let out = "";
|
|
135
|
+
for (const p of t.pentagons)
|
|
136
|
+
out += s.panel(p, base, { ink: true });
|
|
137
|
+
out += s.strokes(t.edges, mix(base, -0.2), 1.1);
|
|
138
|
+
return out + lit(s, t.edges, 0.55);
|
|
139
|
+
},
|
|
140
|
+
});
|
|
141
|
+
const BLUE = { ground: "#f4f6fb", main: "#1f56c4", dark: "#12306f" };
|
|
142
|
+
const RED = { ground: "#f8f4f2", main: "#d8312f", dark: "#6e1313" };
|
|
143
|
+
const NIGHT = { ground: "#16275a", main: "#f2c230", dark: "#0a1230" };
|
|
144
|
+
const CYAN = { ground: "#f4f8fa", main: "#12a8c8", dark: "#143a52" };
|
|
145
|
+
const MAGENTA = { ground: "#faf4f8", main: "#d62a8c", dark: "#4a1a52" };
|
|
146
|
+
const LIME = { ground: "#f6f9ee", main: "#5fb81a", dark: "#1b3a12" };
|
|
147
|
+
const FIRE = { ground: "#f6f1e8", main: "#ff6a13", dark: "#1b1b1f" };
|
|
148
|
+
const ICE = { ground: "#f2f6fa", main: "#1e8cff", dark: "#0d1b3d" };
|
|
149
|
+
const TOXIC = { ground: "#f3f6ea", main: "#2bbf5a", dark: "#241a3a" };
|
|
150
|
+
const CHEV_RED = { ground: "#f8f6f2", main: "#d6312e", dark: "#1f2128" };
|
|
151
|
+
const CHEV_GREEN = { ground: "#f8f6ee", main: "#1fa65a", dark: "#f0c81c" };
|
|
152
|
+
const CHEV_BLUE = { ground: "#f6f7fa", main: "#1f5fbf", dark: "#f08a24" };
|
|
153
|
+
const SWIRL_BLUE = { ground: "#f6f6f2", main: "#1f5fbf", dark: "#143f86" };
|
|
154
|
+
const SWIRL_RED = { ground: "#1f2128", main: "#d6312e", dark: "#d6312e" };
|
|
155
|
+
const SWIRL_TEAL = { ground: "#14b0c8", main: "#f08a24", dark: "#0c6d80" };
|
|
156
|
+
const GOLD = { ground: "#e3b73a", main: "#e3b73a", dark: "#7a560f" };
|
|
157
|
+
const SILVER = { ground: "#cdd3db", main: "#cdd3db", dark: "#4d5662" };
|
|
158
|
+
const COBALT = { ground: "#5b93e0", main: "#5b93e0", dark: "#15306a" };
|
|
159
|
+
export const BALL_SOCCER_STARS_BLUE = /* @__PURE__ */ ball("ball:soccer-stars-blue", "Soccer, stars, blue", "星柄・青", stars(BLUE));
|
|
160
|
+
export const BALL_SOCCER_STARS_RED = /* @__PURE__ */ ball("ball:soccer-stars-red", "Soccer, stars, red", "星柄・赤", stars(RED));
|
|
161
|
+
export const BALL_SOCCER_STARS_NIGHT = /* @__PURE__ */ ball("ball:soccer-stars-night", "Soccer, stars, night", "星柄・夜空", stars(NIGHT));
|
|
162
|
+
export const BALL_SOCCER_HEXAGONS_CYAN = /* @__PURE__ */ ball("ball:soccer-hexagons-cyan", "Soccer, hexagons, cyan", "六角形柄・シアン", hexagons(CYAN));
|
|
163
|
+
export const BALL_SOCCER_HEXAGONS_MAGENTA = /* @__PURE__ */ ball("ball:soccer-hexagons-magenta", "Soccer, hexagons, magenta", "六角形柄・マゼンタ", hexagons(MAGENTA));
|
|
164
|
+
export const BALL_SOCCER_HEXAGONS_LIME = /* @__PURE__ */ ball("ball:soccer-hexagons-lime", "Soccer, hexagons, lime", "六角形柄・ライム", hexagons(LIME));
|
|
165
|
+
export const BALL_SOCCER_FLAMES_FIRE = /* @__PURE__ */ ball("ball:soccer-flames-fire", "Soccer, flames, fire", "炎柄・ファイア", flames(FIRE, "#ffd21f"));
|
|
166
|
+
export const BALL_SOCCER_FLAMES_ICE = /* @__PURE__ */ ball("ball:soccer-flames-ice", "Soccer, flames, ice", "炎柄・アイス", flames(ICE, "#c4e8ff"));
|
|
167
|
+
export const BALL_SOCCER_FLAMES_TOXIC = /* @__PURE__ */ ball("ball:soccer-flames-toxic", "Soccer, flames, toxic", "炎柄・トキシック", flames(TOXIC, "#dcf23a"));
|
|
168
|
+
export const BALL_SOCCER_CHEVRONS_RED = /* @__PURE__ */ ball("ball:soccer-chevrons-red", "Soccer, chevrons, red", "シェブロン柄・赤", chevrons(CHEV_RED));
|
|
169
|
+
export const BALL_SOCCER_CHEVRONS_GREEN = /* @__PURE__ */ ball("ball:soccer-chevrons-green", "Soccer, chevrons, green", "シェブロン柄・緑", chevrons(CHEV_GREEN));
|
|
170
|
+
export const BALL_SOCCER_CHEVRONS_BLUE = /* @__PURE__ */ ball("ball:soccer-chevrons-blue", "Soccer, chevrons, blue", "シェブロン柄・青", chevrons(CHEV_BLUE));
|
|
171
|
+
export const BALL_SOCCER_SWIRL_BLUE = /* @__PURE__ */ ball("ball:soccer-swirl-blue", "Soccer, swirl, blue", "渦巻き柄・青", swirl(SWIRL_BLUE));
|
|
172
|
+
export const BALL_SOCCER_SWIRL_RED = /* @__PURE__ */ ball("ball:soccer-swirl-red", "Soccer, swirl, red", "渦巻き柄・赤", swirl(SWIRL_RED));
|
|
173
|
+
export const BALL_SOCCER_SWIRL_TEAL = /* @__PURE__ */ ball("ball:soccer-swirl-teal", "Soccer, swirl, teal", "渦巻き柄・ティール", swirl(SWIRL_TEAL));
|
|
174
|
+
export const BALL_SOCCER_METALLIC_GOLD = /* @__PURE__ */ ball("ball:soccer-metallic-gold", "Soccer, metallic, gold", "メタリック・金", metallic(GOLD));
|
|
175
|
+
export const BALL_SOCCER_METALLIC_SILVER = /* @__PURE__ */ ball("ball:soccer-metallic-silver", "Soccer, metallic, silver", "メタリック・銀", metallic(SILVER));
|
|
176
|
+
export const BALL_SOCCER_METALLIC_COBALT = /* @__PURE__ */ ball("ball:soccer-metallic-cobalt", "Soccer, metallic, cobalt", "メタリック・コバルト", metallic(COBALT));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type BallSpec } from "./ball.engine.ts";
|
|
2
|
+
/** The late 1800s: eight long panels sewn by hand with a visible cross of thread, and a button where they meet at each end. */
|
|
3
|
+
export declare const BALL_SOCCER_1870_HAND_STITCHED: import("./ball.core.ts").Piece<BallSpec>;
|
|
4
|
+
/** The 1900s: eight panels, a round cap at each end, and a slit across which a lace is drawn to shut the casing once the bladder is in. */
|
|
5
|
+
export declare const BALL_SOCCER_1900_LACED: import("./ball.core.ts").Piece<BallSpec>;
|
|
6
|
+
/** The 1930s: eighteen strips, six panels of three, in two tones of leather, the seams stitched in two rows. */
|
|
7
|
+
export declare const BALL_SOCCER_1930_18_PANEL: import("./ball.core.ts").Piece<BallSpec>;
|
|
8
|
+
/** The 1950s: twelve pentagons, in four tones of chestnut leather so that no two that touch match, the seams stitched. */
|
|
9
|
+
export declare const BALL_SOCCER_1950_12_PANEL: import("./ball.core.ts").Piece<BallSpec>;
|
|
10
|
+
/** The 1960s: the 32 panels (twelve pentagons and twenty hexagons) in leather, tan hexagons and chestnut pentagons, stitched along the seams. */
|
|
11
|
+
export declare const BALL_SOCCER_1960_32_PANEL_LEATHER: import("./ball.core.ts").Piece<BallSpec>;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
// Vintage soccer balls, in worn leather (tan, brown, chestnut) with the stitching of their time, each on the construction of its period: the hand-stitched casing of the late 1800s (eight long panels and a
|
|
2
|
+
// button at each end), the laced ball of the 1900s (eight panels, a round cap at each end and a lace across a slit), the 18 strips of the 1930s (six panels of three strips), the 12 panels of the
|
|
3
|
+
// 1950s and the 32 panels of the 1960s. The panels are our own layouts of the sources in docs/references.md; no maker's ball, mark or pattern is drawn.
|
|
4
|
+
import { defineBall } from "./ball.engine.js";
|
|
5
|
+
import { blend, mix } from "./ball.core.js";
|
|
6
|
+
import { across, lacing, noise, running, scuffs } from "./ball.decal.js";
|
|
7
|
+
import { paint18, seams18 } from "./ball.family.panelled.js";
|
|
8
|
+
import { smallCircle } from "./ball.math.js";
|
|
9
|
+
import { truncatedIcosahedron } from "./ball.polyhedra.js";
|
|
10
|
+
import { dodecahedron, gorePoint, gores } from "./ball.tilings.js";
|
|
11
|
+
import { SOCCER_SIZE } from "./ball.soccer.size.js";
|
|
12
|
+
/** The ball the Laws describe from 1872: a sphere 27 to 28 inches (68.6 to 71.1 cm) round. The Laws' mass for the early years is left out, because the secondary sources read disagree on the figure and the year. */
|
|
13
|
+
const OLD_SIZE = {
|
|
14
|
+
extentMm: 698.5 / Math.PI,
|
|
15
|
+
diameterMm: 698.5 / Math.PI,
|
|
16
|
+
circumferenceMm: 698.5,
|
|
17
|
+
rule: "Laws of the Game of the Football Association, revised 1872: the ball is a sphere 27 to 28 inches round",
|
|
18
|
+
note: "Before 1872 there was no rule. Diameter worked out from the middle of the circumference range. No mass is given, because the early figures could not be confirmed in a primary text.",
|
|
19
|
+
};
|
|
20
|
+
const LEATHER = { gloss: 0.22, shade: "#2b1608", grain: { f: 2.1, a: 0.34 } };
|
|
21
|
+
const THREAD = "#e9d8b0";
|
|
22
|
+
/** A tone of leather: no two panels of old leather are alike. */
|
|
23
|
+
const tone = (base, i, spread = 0.2) => mix(base, (noise(i, 4) - 0.5) * spread);
|
|
24
|
+
/** The seam of leather: a dark crease, with the highlight of its raised edge. */
|
|
25
|
+
const crease = (s, seams, colour, width = 1.3) => s.strokes(seams, colour, width) + s.strokes(seams, "#fff", width * 0.3, { deco: true, opacity: 0.3, dx: 0.25, dy: 0.3 });
|
|
26
|
+
const spec = (base, view, draw, shade = LEATHER.shade) => ({ view, base, mat: { ...LEATHER, shade }, draw });
|
|
27
|
+
/** The long gores, each one panel painted in a tone of the leather (a gore is a lune, so it is cut at the limb as one piece). */
|
|
28
|
+
function paintGores(s, g, base) {
|
|
29
|
+
let out = "";
|
|
30
|
+
g.panels.forEach((ring, i) => {
|
|
31
|
+
out += s.panel(ring, tone(base, i), { n: 1 });
|
|
32
|
+
});
|
|
33
|
+
return out;
|
|
34
|
+
}
|
|
35
|
+
const POLES = [(g) => g.seams[0][0], (g) => g.seams[0][g.seams[0].length - 1]];
|
|
36
|
+
/** The late 1800s: eight long panels sewn by hand with a visible cross of thread, and a button where they meet at each end. */
|
|
37
|
+
export const BALL_SOCCER_1870_HAND_STITCHED = /* @__PURE__ */ defineBall({
|
|
38
|
+
id: "ball:soccer-1870-hand-stitched",
|
|
39
|
+
en: "Soccer ball, hand-stitched",
|
|
40
|
+
ja: "手縫いのサッカーボール",
|
|
41
|
+
size: OLD_SIZE,
|
|
42
|
+
spec: spec("#b98a55", { yaw: 20, pitch: 28, roll: -8 }, (s, base, accent) => {
|
|
43
|
+
const g = gores(8, 0, [0, 28, 0], 24, 4);
|
|
44
|
+
let out = paintGores(s, g, base);
|
|
45
|
+
out += scuffs(s, mix(base, -0.6), mix(base, 0.55), { dark: 18, pale: 8, seed: 2 });
|
|
46
|
+
out += crease(s, g.seams, mix(base, -0.62));
|
|
47
|
+
out += s.strokes(across(g.seams, 0.085, 0.024, 0.013), accent ?? THREAD, 0.75, { deco: true });
|
|
48
|
+
for (const pole of POLES) {
|
|
49
|
+
out += s.dots([pole(g)], 0.1, mix(base, -0.38), { light: true });
|
|
50
|
+
out += s.dots([pole(g)], 0.045, mix(base, -0.62), { light: false });
|
|
51
|
+
}
|
|
52
|
+
return out;
|
|
53
|
+
}),
|
|
54
|
+
});
|
|
55
|
+
/** The 1900s: eight panels, a round cap at each end, and a slit across which a lace is drawn to shut the casing once the bladder is in. */
|
|
56
|
+
export const BALL_SOCCER_1900_LACED = /* @__PURE__ */ defineBall({
|
|
57
|
+
id: "ball:soccer-1900-laced",
|
|
58
|
+
en: "Soccer ball, laced",
|
|
59
|
+
ja: "紐つきのサッカーボール",
|
|
60
|
+
size: OLD_SIZE,
|
|
61
|
+
spec: spec("#8a5a30", { yaw: 24, pitch: 22, roll: 6 }, (s, base, accent) => {
|
|
62
|
+
const g = gores(8, 0, [0, 18, 0], 24, 4);
|
|
63
|
+
const at = gorePoint(8, 0, [0, 18, 0]);
|
|
64
|
+
let out = paintGores(s, g, base);
|
|
65
|
+
const poles = POLES.map((p) => p(g));
|
|
66
|
+
const rim = poles.map((p) => smallCircle(p, 0.32, 40));
|
|
67
|
+
poles.forEach((p, i) => {
|
|
68
|
+
out += s.panel(rim[i], mix(base, -0.16), { n: 1 });
|
|
69
|
+
});
|
|
70
|
+
out += scuffs(s, mix(base, -0.6), mix(base, 0.5), { dark: 18, pale: 8, seed: 5 });
|
|
71
|
+
out += crease(s, g.seams.map((c) => c.slice(3, 22)), mix(base, -0.62), 1.2) + crease(s, rim, mix(base, -0.62), 1.2);
|
|
72
|
+
out += s.strokes(across(g.seams.map((c) => c.slice(3, 22)), 0.1, 0.02), accent ?? THREAD, 0.6, { deco: true });
|
|
73
|
+
const lace = lacing(at(7, 0.5, 0), at(7, 0.5, 0.2), 0.62, 6, 0.032);
|
|
74
|
+
out += s.stroke(lace.slit, mix(base, -0.75), 2.4);
|
|
75
|
+
out += s.dots(lace.eyelets, 0.011, mix(base, -0.7), { light: false });
|
|
76
|
+
out += s.strokes(lace.crossings, accent ?? THREAD, 0.85, { deco: true });
|
|
77
|
+
out += s.strokes(lace.ends, accent ?? THREAD, 0.85, { deco: true });
|
|
78
|
+
return out;
|
|
79
|
+
}),
|
|
80
|
+
});
|
|
81
|
+
/** The 1930s: eighteen strips, six panels of three, in two tones of leather, the seams stitched in two rows. */
|
|
82
|
+
export const BALL_SOCCER_1930_18_PANEL = /* @__PURE__ */ defineBall({
|
|
83
|
+
id: "ball:soccer-1930-18-panel",
|
|
84
|
+
en: "Soccer ball, 18 strips",
|
|
85
|
+
ja: "18枚貼りの革ボール",
|
|
86
|
+
size: OLD_SIZE,
|
|
87
|
+
spec: spec("#9c4f26", { yaw: 28, pitch: 22, roll: 0 }, (s, base, accent) => {
|
|
88
|
+
const light = blend(base, "#d9a56a", 0.55);
|
|
89
|
+
const seams = seams18();
|
|
90
|
+
let out = paint18(s, [[base, light], [light, base], [base, light], [light, base], [base, light], [light, base]]);
|
|
91
|
+
out += scuffs(s, mix(base, -0.6), mix(base, 0.55), { dark: 11, pale: 5, seed: 3 });
|
|
92
|
+
out += crease(s, seams, mix(base, -0.6), 1.15);
|
|
93
|
+
out += s.strokes(running(seams, 0.13), accent ?? THREAD, 0.6, { deco: true });
|
|
94
|
+
return out;
|
|
95
|
+
}),
|
|
96
|
+
});
|
|
97
|
+
/** The 1950s: twelve pentagons, in four tones of chestnut leather so that no two that touch match, the seams stitched. */
|
|
98
|
+
export const BALL_SOCCER_1950_12_PANEL = /* @__PURE__ */ defineBall({
|
|
99
|
+
id: "ball:soccer-1950-12-panel",
|
|
100
|
+
en: "Soccer ball, 12 panels",
|
|
101
|
+
ja: "12枚貼りの革ボール",
|
|
102
|
+
size: OLD_SIZE,
|
|
103
|
+
spec: spec("#7a3a1c", { yaw: 30, pitch: 24, roll: 8 }, (s, base, accent) => {
|
|
104
|
+
const g = dodecahedron();
|
|
105
|
+
const fill = [mix(base, 0.1), mix(base, -0.12), mix(base, 0.26), mix(base, 0.02)];
|
|
106
|
+
let out = "";
|
|
107
|
+
g.panels.forEach((p, i) => {
|
|
108
|
+
out += s.panel(p, fill[g.colour[i]], { n: 6, ink: g.colour[i] === 1 });
|
|
109
|
+
});
|
|
110
|
+
out += scuffs(s, mix(base, -0.6), mix(base, 0.55), { dark: 12, pale: 5, seed: 7 });
|
|
111
|
+
out += crease(s, g.seams, mix(base, -0.6), 1.2);
|
|
112
|
+
out += s.strokes(running(g.seams, 0.11), accent ?? THREAD, 0.55, { deco: true });
|
|
113
|
+
return out;
|
|
114
|
+
}),
|
|
115
|
+
});
|
|
116
|
+
/** The 1960s: the 32 panels (twelve pentagons and twenty hexagons) in leather, tan hexagons and chestnut pentagons, stitched along the seams. */
|
|
117
|
+
export const BALL_SOCCER_1960_32_PANEL_LEATHER = /* @__PURE__ */ defineBall({
|
|
118
|
+
id: "ball:soccer-1960-32-panel-leather",
|
|
119
|
+
en: "Soccer ball, 32 leather",
|
|
120
|
+
ja: "32枚貼りの革ボール",
|
|
121
|
+
size: SOCCER_SIZE,
|
|
122
|
+
spec: {
|
|
123
|
+
...spec("#6e3517", { yaw: 30, pitch: 24, roll: 8 }, (s, base, accent) => {
|
|
124
|
+
const t = truncatedIcosahedron();
|
|
125
|
+
let out = "";
|
|
126
|
+
for (const p of t.pentagons)
|
|
127
|
+
out += s.panel(p, base, { ink: true });
|
|
128
|
+
out += scuffs(s, mix(base, -0.5), "#f0d2a8", { dark: 6, pale: 3, seed: 11 });
|
|
129
|
+
out += crease(s, t.edges, mix(base, -0.55), 1.1);
|
|
130
|
+
out += s.strokes(running(t.edges, 0.13), accent ?? THREAD, 0.5, { deco: true });
|
|
131
|
+
return out;
|
|
132
|
+
}),
|
|
133
|
+
ground: "#d6a976",
|
|
134
|
+
},
|
|
135
|
+
});
|
|
@@ -58,4 +58,30 @@ export interface Gores {
|
|
|
58
58
|
* whole is then tilted by the rotation `tilt` (yaw, pitch and roll in degrees) so that the poles are not on the ball's spin axis.
|
|
59
59
|
*/
|
|
60
60
|
export declare function gores(count?: number, twist?: number, tilt?: readonly [number, number, number], steps?: number, bands?: number): Gores;
|
|
61
|
+
/** The point of a gore: gore `i` of `count`, `u` of the way across it (0 on its left seam, 1 on its right) and `s` from the south pole (-1) to the north (1), turned by `tilt` like `gores`. */
|
|
62
|
+
export declare function gorePoint(count?: number, twist?: number, tilt?: readonly [number, number, number]): (i: number, u: number, s: number) => V3;
|
|
63
|
+
/** Colours the centres with `k` colours so that no two neighbours (centres at angle `gap` or less apart) share one, by search; the result is the colour of each. */
|
|
64
|
+
export declare function colourCentres(centres: readonly V3[], gap: number, k?: number): number[];
|
|
65
|
+
type Icosahedron = Tiling & {
|
|
66
|
+
colour: number[];
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* The 20-panel layout: an icosahedron. Its 12 vertices are the cyclic permutations of (0, +-1, +-phi); its 20 triangles are about the directions of a dodecahedron's vertices. `colour` is a
|
|
70
|
+
* four-colouring of the triangles (no two that share an edge match), found by search.
|
|
71
|
+
*/
|
|
72
|
+
export declare function icosahedron(): Icosahedron;
|
|
73
|
+
export interface Octahedron {
|
|
74
|
+
/** The eight triangular panels, with their edges bent into S curves (dense rings: use one sample per edge). */
|
|
75
|
+
panels: V3[][];
|
|
76
|
+
centres: V3[];
|
|
77
|
+
/** Every one of the 12 edges once, as an S curve from one end to the other. */
|
|
78
|
+
seams: V3[][];
|
|
79
|
+
/** 0 or 1, so that no two panels that share an edge match. */
|
|
80
|
+
parity: number[];
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* The 8-panel layout: an octahedron whose twelve edges are bent into S curves, a quarter of the way along to one side and three quarters of the way to the other, so the eight triangles are
|
|
84
|
+
* twisted into curved panels. The curve is the same turned half a turn about the edge's middle, and it is carried to itself by the cube's rotations, so the panels are alike and the layout has a hand.
|
|
85
|
+
*/
|
|
86
|
+
export declare function octahedron8(lift?: number, steps?: number): Octahedron;
|
|
61
87
|
export {};
|
|
@@ -210,3 +210,90 @@ export function gores(count = 6, twist = 150, tilt = [0, 0, 0], steps = 24, band
|
|
|
210
210
|
}
|
|
211
211
|
return { panels, centres, seams, pieces };
|
|
212
212
|
}
|
|
213
|
+
/** The point of a gore: gore `i` of `count`, `u` of the way across it (0 on its left seam, 1 on its right) and `s` from the south pole (-1) to the north (1), turned by `tilt` like `gores`. */
|
|
214
|
+
export function gorePoint(count = 6, twist = 150, tilt = [0, 0, 0]) {
|
|
215
|
+
const m = rotation((tilt[0] * Math.PI) / 180, (tilt[1] * Math.PI) / 180, (tilt[2] * Math.PI) / 180);
|
|
216
|
+
return (i, u, s) => apply(m, lonLat((2 * Math.PI * (i + u)) / count + ((twist * Math.PI) / 180) * (s / 2), (s * Math.PI) / 2));
|
|
217
|
+
}
|
|
218
|
+
/** Colours the centres with `k` colours so that no two neighbours (centres at angle `gap` or less apart) share one, by search; the result is the colour of each. */
|
|
219
|
+
export function colourCentres(centres, gap, k = 4) {
|
|
220
|
+
const colour = centres.map(() => -1);
|
|
221
|
+
const next = (i, j) => dot(centres[i], centres[j]) > Math.cos(gap) - 1e-6 && i !== j;
|
|
222
|
+
const paint = (i) => {
|
|
223
|
+
if (i === centres.length)
|
|
224
|
+
return true;
|
|
225
|
+
for (let c = 0; c < k; c++) {
|
|
226
|
+
if (centres.every((_, j) => j >= i || !next(i, j) || colour[j] !== c)) {
|
|
227
|
+
colour[i] = c;
|
|
228
|
+
if (paint(i + 1))
|
|
229
|
+
return true;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
colour[i] = -1;
|
|
233
|
+
return false;
|
|
234
|
+
};
|
|
235
|
+
paint(0);
|
|
236
|
+
return colour;
|
|
237
|
+
}
|
|
238
|
+
let icosa;
|
|
239
|
+
/**
|
|
240
|
+
* The 20-panel layout: an icosahedron. Its 12 vertices are the cyclic permutations of (0, +-1, +-phi); its 20 triangles are about the directions of a dodecahedron's vertices. `colour` is a
|
|
241
|
+
* four-colouring of the triangles (no two that share an edge match), found by search.
|
|
242
|
+
*/
|
|
243
|
+
export function icosahedron() {
|
|
244
|
+
if (icosa !== undefined)
|
|
245
|
+
return icosa;
|
|
246
|
+
const verts = [];
|
|
247
|
+
for (const a of signs)
|
|
248
|
+
for (const b of signs)
|
|
249
|
+
verts.push(norm([0, a, b * PHI]), norm([a, b * PHI, 0]), norm([b * PHI, 0, a]));
|
|
250
|
+
const near = (a, b) => Math.abs(dot(a, b) - 1 / Math.sqrt(5)) < 1e-6;
|
|
251
|
+
const centres = [];
|
|
252
|
+
for (let i = 0; i < 12; i++)
|
|
253
|
+
for (let j = i + 1; j < 12; j++)
|
|
254
|
+
for (let k = j + 1; k < 12; k++)
|
|
255
|
+
if (near(verts[i], verts[j]) && near(verts[i], verts[k]) && near(verts[j], verts[k]))
|
|
256
|
+
centres.push(norm(add(add(verts[i], verts[j]), verts[k])));
|
|
257
|
+
const t = tiling(verts, centres, centres.map(() => 0), 5);
|
|
258
|
+
// Triangles that share an edge have centres at the angle whose cosine is sqrt 5 / 3.
|
|
259
|
+
icosa = { ...t, colour: colourCentres(centres, Math.acos(Math.sqrt(5) / 3) + 1e-6, 4) };
|
|
260
|
+
return icosa;
|
|
261
|
+
}
|
|
262
|
+
const octas = new Map();
|
|
263
|
+
/**
|
|
264
|
+
* The 8-panel layout: an octahedron whose twelve edges are bent into S curves, a quarter of the way along to one side and three quarters of the way to the other, so the eight triangles are
|
|
265
|
+
* twisted into curved panels. The curve is the same turned half a turn about the edge's middle, and it is carried to itself by the cube's rotations, so the panels are alike and the layout has a hand.
|
|
266
|
+
*/
|
|
267
|
+
export function octahedron8(lift = 0.16, steps = 14) {
|
|
268
|
+
const hit = octas.get(lift * 1000 + steps);
|
|
269
|
+
if (hit !== undefined)
|
|
270
|
+
return hit;
|
|
271
|
+
const edge = (a, b) => {
|
|
272
|
+
const [p, q] = keyOf(a) < keyOf(b) ? [a, b] : [b, a];
|
|
273
|
+
const pts = Array.from({ length: steps + 1 }, (_, j) => bent(p, q, j / steps, lift, 0.5));
|
|
274
|
+
return keyOf(a) < keyOf(b) ? pts : pts.reverse();
|
|
275
|
+
};
|
|
276
|
+
const panels = [];
|
|
277
|
+
const centres = [];
|
|
278
|
+
const parity = [];
|
|
279
|
+
const seams = [];
|
|
280
|
+
const seen = new Set();
|
|
281
|
+
for (const sx of signs)
|
|
282
|
+
for (const sy of signs)
|
|
283
|
+
for (const sz of signs) {
|
|
284
|
+
const a = [sx, 0, 0], b = [0, sy, 0], c = [0, 0, sz];
|
|
285
|
+
panels.push([...edge(a, b).slice(0, -1), ...edge(b, c).slice(0, -1), ...edge(c, a).slice(0, -1)]);
|
|
286
|
+
centres.push(norm([sx, sy, sz]));
|
|
287
|
+
parity.push(sx * sy * sz > 0 ? 0 : 1);
|
|
288
|
+
for (const [p, q] of [[a, b], [b, c], [c, a]]) {
|
|
289
|
+
const key = [keyOf(p), keyOf(q)].sort().join("|");
|
|
290
|
+
if (seen.has(key))
|
|
291
|
+
continue;
|
|
292
|
+
seen.add(key);
|
|
293
|
+
seams.push(edge(p, q));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const result = { panels, centres, seams, parity };
|
|
297
|
+
octas.set(lift * 1000 + steps, result);
|
|
298
|
+
return result;
|
|
299
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type BallSpec } from "./ball.engine.ts";
|
|
2
|
+
export declare const BALL_VOLLEYBALL_COLOURS: import("./ball.core.ts").Piece<BallSpec>;
|
|
3
|
+
export declare const BALL_VOLLEYBALL_BRAZIL: import("./ball.core.ts").Piece<BallSpec>;
|
|
4
|
+
export declare const BALL_VOLLEYBALL_JAPAN: import("./ball.core.ts").Piece<BallSpec>;
|
|
5
|
+
export declare const BALL_VOLLEYBALL_CANADA: import("./ball.core.ts").Piece<BallSpec>;
|
|
6
|
+
export declare const BALL_VOLLEYBALL_USA: import("./ball.core.ts").Piece<BallSpec>;
|
|
7
|
+
export declare const BALL_VOLLEYBALL_ITALY: import("./ball.core.ts").Piece<BallSpec>;
|
|
8
|
+
export declare const BALL_VOLLEYBALL_POLAND: import("./ball.core.ts").Piece<BallSpec>;
|
|
9
|
+
export declare const BALL_VOLLEYBALL_FRANCE: import("./ball.core.ts").Piece<BallSpec>;
|
|
10
|
+
export declare const BALL_VOLLEYBALL_SERBIA: import("./ball.core.ts").Piece<BallSpec>;
|
|
11
|
+
export declare const BALL_VOLLEYBALL_NETHERLANDS: import("./ball.core.ts").Piece<BallSpec>;
|
|
12
|
+
export declare const BALL_VOLLEYBALL_GERMANY: import("./ball.core.ts").Piece<BallSpec>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Volleyballs in national colours: the 18-panel indoor ball (six groups of three strips) with its panels in the colours of a country's flag, three colours to a ball. They are only colours: no flag is drawn,
|
|
2
|
+
// no crest or federation's mark, and the ball is the indoor ball of the FIVB's rule. `colors` takes any three colours for any of them, and `ball:volleyball-colours` is the same ball with colours of your own.
|
|
3
|
+
import { defineBall } from "./ball.engine.js";
|
|
4
|
+
import { strips18 } from "./ball.family.panelled.js";
|
|
5
|
+
import { BALL_VOLLEYBALL } from "./ball.volleyball.js";
|
|
6
|
+
const WHITE = "#f6f4ee";
|
|
7
|
+
/** The ball with the colours of one flag: `tint` replaces the first colour, `accent` the second and `colors` all three. The six faces take the three colours in pairs, so each colour is the outer strips of two faces and the middle strip of two others. */
|
|
8
|
+
function nation(id, en, ja, colours, view = { yaw: 28, pitch: 22, roll: 0 }) {
|
|
9
|
+
return defineBall({
|
|
10
|
+
id,
|
|
11
|
+
en,
|
|
12
|
+
ja,
|
|
13
|
+
size: BALL_VOLLEYBALL.size,
|
|
14
|
+
spec: {
|
|
15
|
+
view,
|
|
16
|
+
base: colours[0],
|
|
17
|
+
ground: "#e9e7e0",
|
|
18
|
+
mat: { gloss: 0.75, shade: "#1a2a50", grain: { f: 1.2, a: 0.12 } },
|
|
19
|
+
draw: (s, base, accent, picked) => {
|
|
20
|
+
const [a, b, c] = picked ?? [base, accent ?? colours[1], colours[2]];
|
|
21
|
+
return strips18(s, [[a, b], [b, c], [c, a], [a, c], [b, a], [c, b]], "#3a4560");
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export const BALL_VOLLEYBALL_COLOURS = /* @__PURE__ */ nation("ball:volleyball-colours", "Volleyball, three colours", "三色のバレーボール", ["#f3c81c", "#1f5fbf", WHITE]);
|
|
27
|
+
export const BALL_VOLLEYBALL_BRAZIL = /* @__PURE__ */ nation("ball:volleyball-brazil", "Volleyball, Brazil", "バレー(ブラジル)", ["#009c3b", "#ffdf00", "#002776"]);
|
|
28
|
+
export const BALL_VOLLEYBALL_JAPAN = /* @__PURE__ */ nation("ball:volleyball-japan", "Volleyball, Japan", "バレー(日本)", [WHITE, "#bc002d", "#7d0020"]);
|
|
29
|
+
export const BALL_VOLLEYBALL_CANADA = /* @__PURE__ */ nation("ball:volleyball-canada", "Volleyball, Canada", "バレー(カナダ)", ["#d52b1e", WHITE, "#9b1c14"]);
|
|
30
|
+
export const BALL_VOLLEYBALL_USA = /* @__PURE__ */ nation("ball:volleyball-usa", "Volleyball, USA", "バレー(アメリカ)", ["#b22234", WHITE, "#3c3b6e"]);
|
|
31
|
+
export const BALL_VOLLEYBALL_ITALY = /* @__PURE__ */ nation("ball:volleyball-italy", "Volleyball, Italy", "バレー(イタリア)", ["#009246", WHITE, "#ce2b37"]);
|
|
32
|
+
export const BALL_VOLLEYBALL_POLAND = /* @__PURE__ */ nation("ball:volleyball-poland", "Volleyball, Poland", "バレー(ポーランド)", [WHITE, "#dc143c", "#9b1030"]);
|
|
33
|
+
export const BALL_VOLLEYBALL_FRANCE = /* @__PURE__ */ nation("ball:volleyball-france", "Volleyball, France", "バレー(フランス)", ["#0055a4", WHITE, "#ef4135"]);
|
|
34
|
+
export const BALL_VOLLEYBALL_SERBIA = /* @__PURE__ */ nation("ball:volleyball-serbia", "Volleyball, Serbia", "バレー(セルビア)", ["#c6363c", "#0c4076", WHITE]);
|
|
35
|
+
export const BALL_VOLLEYBALL_NETHERLANDS = /* @__PURE__ */ nation("ball:volleyball-netherlands", "Volleyball, Netherlands", "バレー(オランダ)", ["#ae1c28", WHITE, "#21468b"]);
|
|
36
|
+
export const BALL_VOLLEYBALL_GERMANY = /* @__PURE__ */ nation("ball:volleyball-germany", "Volleyball, Germany", "バレー(ドイツ)", ["#1b1b1b", "#dd0000", "#ffce00"]);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PuckFace } from "./ball/ball.face.ts";
|
|
1
|
+
import type { FlagRenderer, PuckFace } from "./ball/ball.face.ts";
|
|
2
2
|
/** `metal`: full colour with a gradient. `line`: one outline in `currentColor`. `color`: flat fills of the main colour, with no gradient. */
|
|
3
3
|
export type EmblemStyle = "metal" | "line" | "color";
|
|
4
4
|
export declare const EMBLEM_STYLES: readonly ["metal", "line", "color"];
|
|
@@ -53,9 +53,13 @@ export interface EmblemOptions {
|
|
|
53
53
|
turnBox?: boolean;
|
|
54
54
|
/**
|
|
55
55
|
* The print on the top face of a puck: the printed pucks (`puck:*`) start from a face of their own and this replaces any part of it, and `ball:puck` given a face is drawn as `puck:souvenir` with it. `image` takes any SVG
|
|
56
|
-
* (made safe first), `emblem` a dougu id, `flag` a country code (`ca` and `us` are drawn here; another needs `flags
|
|
56
|
+
* (made safe first), `emblem` a dougu id, `flag` a country code (`ca` and `us` are drawn here; another needs the `flags` option, a renderer like hata's). See `PuckFace`. Anything that is not a puck ignores it.
|
|
57
57
|
*/
|
|
58
58
|
face?: PuckFace;
|
|
59
|
+
/** A ball with panels in several colours (the national volleyballs, `ball:volleyball-flag` and the rest): three colours for its panels, each a hex colour or `rgb()`; one that is not a colour is dropped, and fewer than three are repeated. Anything else ignores it. */
|
|
60
|
+
colors?: readonly string[];
|
|
61
|
+
/** A puck: a renderer for the flag codes this package does not draw (`face.flag`): `(code, { shape: "round" | "square" | "rect", size, theme }) => svg`, synchronous, the same as taisen-brackets takes (hata's `flag()` is asynchronous, so load the flags first). */
|
|
62
|
+
flags?: FlagRenderer;
|
|
59
63
|
}
|
|
60
64
|
/** 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. */
|
|
61
65
|
export interface FrameOptions extends EmblemOptions {
|
|
@@ -93,5 +93,55 @@ export const EMBLEM_DESCRIPTIONS = {
|
|
|
93
93
|
"ball:soccer-6": { en: "6 panels, thermobonded (glued, not stitched): six twisted gores with a few long curved seams, and a smooth look", ja: "縫わずに貼り合わせる熱接着の6枚貼り。ねじれた細長いパネル6枚が、長く曲がった数本の継ぎ目でつながり、表面はなめらか" },
|
|
94
94
|
"ball:futsal": { en: "Futsal: size 4, 62 to 64 cm round, 400 to 440 g, low bounce; 32 panels, bright blue and white with a small yellow pentagon on each of the twelve", ja: "フットサル用の4号球。円周62〜64cm、重さ400〜440g、弾みにくい。32枚貼りで、明るい青と白の配色。12枚の五角形それぞれに、小さな黄色の五角形が入る" },
|
|
95
95
|
"ball:beach-soccer": { en: "Beach soccer: size 5, 68 to 70 cm round, 400 to 440 g, soft (low pressure); the 14-panel propeller layout in bright yellow, orange and blue", ja: "ビーチサッカー用の5号球。円周68〜70cm、重さ400〜440g、空気圧が低くやわらかい。14枚貼りのプロペラ形で、黄色、オレンジ、青の明るい配色" },
|
|
96
|
+
"ball:soccer-1870-hand-stitched": { en: "Late 1800s: eight long panels of worn tan leather sewn by hand with a visible cross of thread, and a button where they meet at each end", ja: "1800年代後半の手縫いボール。使い込んだ薄茶色の革の細長いパネル8枚を、糸の十字がはっきり見える縫い目でつなぎ、両端のパネルが集まるところにボタンが付く" },
|
|
97
|
+
"ball:soccer-1900-laced": { en: "1900s: eight panels of brown leather, a round cap at each end, and a slit shut with a criss-crossed lace once the bladder was in", ja: "1900年代の紐つきボール。茶色い革のパネル8枚、両端の丸いキャップ、内袋(ブラダー)を入れたあとに十字に紐を掛けて閉じる切れ目" },
|
|
98
|
+
"ball:soccer-1930-18-panel": { en: "1930s: 18 strips of chestnut and tan leather, six panels of three, the seams stitched", ja: "1930年代の18枚貼り。栗色と薄茶色の革の帯状パネル18枚(3枚ずつ6組)を使い、継ぎ目を縫い合わせたもの" },
|
|
99
|
+
"ball:soccer-1950-12-panel": { en: "1950s: 12 pentagons of chestnut leather in four tones, so that no two that touch match, the seams stitched", ja: "1950年代の12枚貼り。栗色の革の五角形12枚を4種類の色合いにして、隣り合うパネルが同じ色合いにならないようにし、継ぎ目を縫い合わせたもの" },
|
|
100
|
+
"ball:soccer-1960-32-panel-leather": { en: "1960s: the 32 panels (12 pentagons and 20 hexagons) in leather, chestnut pentagons on tan hexagons, stitched along the seams", ja: "1960年代の32枚貼りの革ボール。五角形12枚と六角形20枚を使い、薄茶色の六角形に栗色の五角形を配して、継ぎ目を縫い合わせたもの" },
|
|
101
|
+
"ball:soccer-1970-black-white": { en: "In the style of the early-1970s match balls: 32 panels, black pentagons with a white ring and white hexagons with a pale dished centre and a dot", ja: "1970年代前半の試合球風。32枚貼りで、白い輪のある黒い五角形と、中央に淡いくぼみと点のある白い六角形" },
|
|
102
|
+
"ball:soccer-1978-triad": { en: "In the style of the late-1970s match balls: 32 panels, each hexagon carrying three bold curved triangles in a pinwheel, their points meeting round each pentagon", ja: "1970年代後半の試合球風。32枚貼りで、六角形ごとに太い曲線の三角形を3枚、風車のように配し、その先端が五角形のまわりに集まる" },
|
|
103
|
+
"ball:soccer-1986-decorated-triad": { en: "In the style of the 1980s match balls: the triads in clay red, each blade ornamented with a row of white beads, and dark pentagons ringed in gold", ja: "1980年代の試合球風。素焼きのような赤の三つ巴で、羽根ごとに白い珠の列を飾り、五角形は金の輪をあしらった暗い色にしたもの" },
|
|
104
|
+
"ball:soccer-1998-coloured-triad": { en: "In the style of the 1990s match balls: the triads in blue, red and gold on white hexagons, with deep navy pentagons", ja: "1990年代の試合球風。白い六角形に青、赤、金の三つ巴を配し、五角形は深い紺色にしたもの" },
|
|
105
|
+
"ball:soccer-2002-triangle-sweep": { en: "In the style of the early-2000s match balls: long thin triangles that sweep across each hexagon in graphite, with gold sparks, over charcoal pentagons", ja: "2000年代前半の試合球風。六角形ごとに細長い三角形が黒鉛色で流れるように並び、金色の小さな三角形が添えられ、五角形は炭色" },
|
|
106
|
+
"ball:soccer-2006-propeller": { en: "In the style of the mid-2000s match balls: 14 panels (6 propellers and 8 triangles), a fine gold line inside each propeller and a gold mark on each dark triangle", ja: "2000年代半ばの試合球風。14枚貼り(プロペラ形6枚、三角形8枚)で、各プロペラの内側に細い金の線、暗い色の三角形に金の印が入る" },
|
|
107
|
+
"ball:soccer-2010-grooved": { en: "In the style of the early-2010s match balls: 8 panels (an octahedron whose edges are bent into S curves) with grooves for seams and fine contour lines across each panel", ja: "2010年代前半の試合球風。8枚貼り(辺をS字に曲げた正八面体)で、継ぎ目は溝、各パネルには細い等高線のような線が入る" },
|
|
108
|
+
"ball:soccer-2014-ribbon": { en: "In the style of the mid-2010s match balls: 6 twisted panels in white, crossed by wide ribbons in teal, orange and violet", ja: "2010年代半ばの試合球風。ねじれた6枚貼りの白いボールに、ティール、オレンジ、紫の幅広いリボンが交差する" },
|
|
109
|
+
"ball:soccer-2018-pixel": { en: "In the style of the late-2010s match balls: 6 panels covered with square pixel blocks in graphite, grey, red and gold, thick on one side and thinning out", ja: "2010年代後半の試合球風。6枚貼りで、黒鉛色、灰色、赤、金の四角いピクセルが一方に密集し、反対側へまばらになっていく" },
|
|
110
|
+
"ball:soccer-2022-speed-shell": { en: "In the style of the early-2020s match balls: 20 triangular panels (an icosahedron) in burgundy, cream and gold, each carrying nested outlines like a shell", ja: "2020年代前半の試合球風。20枚貼り(正二十面体)で、えんじ、クリーム、金の三角形のパネルそれぞれに、貝殻のように重なる輪郭線が入る" },
|
|
111
|
+
"ball:soccer-training-high-vis": { en: "A modern high-visibility training ball: 32 panels in fluorescent yellow-green with hot pink pentagons ringed in black and three dark speed marks on each hexagon", ja: "現代の高視認性トレーニングボール。蛍光の黄緑色の32枚貼りで、黒い輪をあしらった濃いピンクの五角形と、六角形ごとに3本の黒い速度線が入る" },
|
|
112
|
+
"ball:soccer-stars-blue": { en: "A shop-wall pattern: a five-pointed star on every panel; the blue colourway", ja: "店頭によくある柄:すべてのパネルに角が5つの星。配色は青" },
|
|
113
|
+
"ball:soccer-stars-red": { en: "A shop-wall pattern: a five-pointed star on every panel; the red colourway", ja: "店頭によくある柄:すべてのパネルに角が5つの星。配色は赤" },
|
|
114
|
+
"ball:soccer-stars-night": { en: "A shop-wall pattern: a five-pointed star on every panel; the gold on night blue colourway", ja: "店頭によくある柄:すべてのパネルに角が5つの星。配色は夜空の紺に金" },
|
|
115
|
+
"ball:soccer-hexagons-cyan": { en: "A shop-wall pattern: two outlines inside each hexagon, one in the other, like a honeycomb, and solid pentagons; the cyan colourway", ja: "店頭によくある柄:六角形の中に二重の輪郭線を入れた蜂の巣のような柄と、塗りつぶした五角形。配色はシアン" },
|
|
116
|
+
"ball:soccer-hexagons-magenta": { en: "A shop-wall pattern: two outlines inside each hexagon, one in the other, like a honeycomb, and solid pentagons; the magenta colourway", ja: "店頭によくある柄:六角形の中に二重の輪郭線を入れた蜂の巣のような柄と、塗りつぶした五角形。配色はマゼンタ" },
|
|
117
|
+
"ball:soccer-hexagons-lime": { en: "A shop-wall pattern: two outlines inside each hexagon, one in the other, like a honeycomb, and solid pentagons; the lime colourway", ja: "店頭によくある柄:六角形の中に二重の輪郭線を入れた蜂の巣のような柄と、塗りつぶした五角形。配色はライム" },
|
|
118
|
+
"ball:soccer-flames-fire": { en: "A shop-wall pattern: five tongues of flame leaving each dark pentagon, an outer one and a lighter inner one; the fire: orange and yellow on black colourway", ja: "店頭によくある柄:暗い色の五角形から外へ伸びる5本の炎。外側の炎と、明るい内側の炎の二重。配色はファイア:黒地にオレンジと黄色" },
|
|
119
|
+
"ball:soccer-flames-ice": { en: "A shop-wall pattern: five tongues of flame leaving each dark pentagon, an outer one and a lighter inner one; the ice: blue and pale blue on navy colourway", ja: "店頭によくある柄:暗い色の五角形から外へ伸びる5本の炎。外側の炎と、明るい内側の炎の二重。配色はアイス:紺地に青と水色" },
|
|
120
|
+
"ball:soccer-flames-toxic": { en: "A shop-wall pattern: five tongues of flame leaving each dark pentagon, an outer one and a lighter inner one; the toxic: green and yellow on deep purple colourway", ja: "店頭によくある柄:暗い色の五角形から外へ伸びる5本の炎。外側の炎と、明るい内側の炎の二重。配色はトキシック:濃い紫地に緑と黄色" },
|
|
121
|
+
"ball:soccer-chevrons-red": { en: "A shop-wall pattern: eight gores from pole to pole, every other one coloured, crossed by three V-shaped bands that make a zigzag round the ball; the red and black colourway", ja: "店頭によくある柄:極から極へ伸びる8枚のパネルを1枚おきに色づけし、3本のV字の帯を重ねて、ボールを一周するジグザグにしたもの。配色は赤と黒" },
|
|
122
|
+
"ball:soccer-chevrons-green": { en: "A shop-wall pattern: eight gores from pole to pole, every other one coloured, crossed by three V-shaped bands that make a zigzag round the ball; the green and yellow colourway", ja: "店頭によくある柄:極から極へ伸びる8枚のパネルを1枚おきに色づけし、3本のV字の帯を重ねて、ボールを一周するジグザグにしたもの。配色は緑と黄色" },
|
|
123
|
+
"ball:soccer-chevrons-blue": { en: "A shop-wall pattern: eight gores from pole to pole, every other one coloured, crossed by three V-shaped bands that make a zigzag round the ball; the blue and orange colourway", ja: "店頭によくある柄:極から極へ伸びる8枚のパネルを1枚おきに色づけし、3本のV字の帯を重ねて、ボールを一周するジグザグにしたもの。配色は青とオレンジ" },
|
|
124
|
+
"ball:soccer-swirl-blue": { en: "A shop-wall pattern: four gores that twist round the ball, two in one colour and two in the other; the blue and white colourway", ja: "店頭によくある柄:ボールを巻くようにねじれた4枚のパネルを、2枚ずつ2色に塗り分けたもの。配色は青と白" },
|
|
125
|
+
"ball:soccer-swirl-red": { en: "A shop-wall pattern: four gores that twist round the ball, two in one colour and two in the other; the red and black colourway", ja: "店頭によくある柄:ボールを巻くようにねじれた4枚のパネルを、2枚ずつ2色に塗り分けたもの。配色は赤と黒" },
|
|
126
|
+
"ball:soccer-swirl-teal": { en: "A shop-wall pattern: four gores that twist round the ball, two in one colour and two in the other; the orange and teal colourway", ja: "店頭によくある柄:ボールを巻くようにねじれた4枚のパネルを、2枚ずつ2色に塗り分けたもの。配色はオレンジとティール" },
|
|
127
|
+
"ball:soccer-metallic-gold": { en: "A shop-wall pattern: 32 panels in a polished metallic finish that mirrors the sky and the ground, a light metal on the hexagons and a dark one on the pentagons; the gold colourway", ja: "店頭によくある柄:空と地面を映す磨いた金属の質感の32枚貼り。六角形は明るい金属、五角形は暗い金属。配色は金" },
|
|
128
|
+
"ball:soccer-metallic-silver": { en: "A shop-wall pattern: 32 panels in a polished metallic finish that mirrors the sky and the ground, a light metal on the hexagons and a dark one on the pentagons; the silver colourway", ja: "店頭によくある柄:空と地面を映す磨いた金属の質感の32枚貼り。六角形は明るい金属、五角形は暗い金属。配色は銀" },
|
|
129
|
+
"ball:soccer-metallic-cobalt": { en: "A shop-wall pattern: 32 panels in a polished metallic finish that mirrors the sky and the ground, a light metal on the hexagons and a dark one on the pentagons; the cobalt blue colourway", ja: "店頭によくある柄:空と地面を映す磨いた金属の質感の32枚貼り。六角形は明るい金属、五角形は暗い金属。配色はコバルトブルー" },
|
|
130
|
+
"ball:baseball-lemon-peel": { en: "The early lemon-peel ball of the 1850s and 1860s: a cover of four pieces and four lines of stitching that meet at two points, in aged leather with dark thread", ja: "1850〜60年代の初期のレモンピール型ボール。4枚の革と、2点で交わる4本の縫い目でできており、古びた革に濃い色の糸" },
|
|
131
|
+
"ball:baseball-red-blue": { en: "The figure-8 seam stitched with alternate red and blue stitches, the American League's laces as a 1930s player remembered them", ja: "8の字の縫い目を赤と青の糸で交互に縫ったもの。1930年代の選手の回想にあるアメリカンリーグのボールの縫い糸" },
|
|
132
|
+
"ball:baseball-black-red": { en: "The figure-8 seam stitched with alternate black and red stitches, the National League's laces as a 1930s player remembered them", ja: "8の字の縫い目を黒と赤の糸で交互に縫ったもの。1930年代の選手の回想にあるナショナルリーグのボールの縫い糸" },
|
|
133
|
+
"ball:baseball-vintage-leather": { en: "The figure-8 ball in aged leather the colour of tea, scuffed, with faded red thread", ja: "茶色く変色して傷のついた古い革に、色あせた赤い糸で8の字に縫ったボール" },
|
|
134
|
+
"ball:softball-11-optic": { en: "The 11 in softball in optic yellow with red stitching: 27.9 cm round, 166.5 to 173.6 g (WBSC Slow Pitch rules)", ja: "11インチの蛍光イエローのソフトボール。赤い縫い目、円周27.9cm、重さ166.5〜173.6g(WBSCスローピッチ規則)" },
|
|
135
|
+
"ball:volleyball-colours": { en: "The 18-panel indoor volleyball with panels in three colours of your own (the `colors` option); yellow, blue and white by default", ja: "3色を自由に指定できる(colors オプション)18枚貼りの室内用バレーボール。初期設定は黄、青、白" },
|
|
136
|
+
"ball:volleyball-brazil": { en: "The 18-panel indoor volleyball in colours taken from the flag: green, yellow and blue. Colours only, no flag or mark is drawn", ja: "国旗の色を取り入れた18枚貼りの室内用バレーボール:緑、黄、青。色だけで、旗や紋章は描かない" },
|
|
137
|
+
"ball:volleyball-japan": { en: "The 18-panel indoor volleyball in colours taken from the flag: white, red and a darker red. Colours only, no flag or mark is drawn", ja: "国旗の色を取り入れた18枚貼りの室内用バレーボール:白、赤、濃い赤。色だけで、旗や紋章は描かない" },
|
|
138
|
+
"ball:volleyball-canada": { en: "The 18-panel indoor volleyball in colours taken from the flag: red, white and a darker red. Colours only, no flag or mark is drawn", ja: "国旗の色を取り入れた18枚貼りの室内用バレーボール:赤、白、濃い赤。色だけで、旗や紋章は描かない" },
|
|
139
|
+
"ball:volleyball-usa": { en: "The 18-panel indoor volleyball in colours taken from the flag: red, white and blue. Colours only, no flag or mark is drawn", ja: "国旗の色を取り入れた18枚貼りの室内用バレーボール:赤、白、青。色だけで、旗や紋章は描かない" },
|
|
140
|
+
"ball:volleyball-italy": { en: "The 18-panel indoor volleyball in colours taken from the flag: green, white and red. Colours only, no flag or mark is drawn", ja: "国旗の色を取り入れた18枚貼りの室内用バレーボール:緑、白、赤。色だけで、旗や紋章は描かない" },
|
|
141
|
+
"ball:volleyball-poland": { en: "The 18-panel indoor volleyball in colours taken from the flag: white, red and a darker red. Colours only, no flag or mark is drawn", ja: "国旗の色を取り入れた18枚貼りの室内用バレーボール:白、赤、濃い赤。色だけで、旗や紋章は描かない" },
|
|
142
|
+
"ball:volleyball-france": { en: "The 18-panel indoor volleyball in colours taken from the flag: blue, white and red. Colours only, no flag or mark is drawn", ja: "国旗の色を取り入れた18枚貼りの室内用バレーボール:青、白、赤。色だけで、旗や紋章は描かない" },
|
|
143
|
+
"ball:volleyball-serbia": { en: "The 18-panel indoor volleyball in colours taken from the flag: red, blue and white. Colours only, no flag or mark is drawn", ja: "国旗の色を取り入れた18枚貼りの室内用バレーボール:赤、青、白。色だけで、旗や紋章は描かない" },
|
|
144
|
+
"ball:volleyball-netherlands": { en: "The 18-panel indoor volleyball in colours taken from the flag: red, white and blue. Colours only, no flag or mark is drawn", ja: "国旗の色を取り入れた18枚貼りの室内用バレーボール:赤、白、青。色だけで、旗や紋章は描かない" },
|
|
145
|
+
"ball:volleyball-germany": { en: "The 18-panel indoor volleyball in colours taken from the flag: black, red and gold. Colours only, no flag or mark is drawn", ja: "国旗の色を取り入れた18枚貼りの室内用バレーボール:黒、赤、金。色だけで、旗や紋章は描かない" },
|
|
96
146
|
...soccerColourways(),
|
|
97
147
|
};
|