@johnmorrisdotca/dougu-sports 0.14.0 → 0.16.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 -0
- package/NOTICE.md +1 -0
- package/README.md +23 -5
- package/dist/emblems/ball/ball.engine.d.ts +6 -0
- package/dist/emblems/ball/ball.engine.js +4 -2
- package/dist/emblems/ball/ball.family.dotted.d.ts +3 -0
- package/dist/emblems/ball/ball.family.dotted.js +3 -0
- package/dist/emblems/ball/ball.holes.d.ts +26 -0
- package/dist/emblems/ball/ball.holes.js +140 -0
- package/dist/emblems/ball/ball.index.js +2 -1
- package/dist/emblems/ball/ball.pickleball.js +3 -0
- package/dist/emblems/ball/ball.plastic.d.ts +1 -0
- package/dist/emblems/ball/ball.plastic.js +32 -0
- package/dist/emblems/emblem.descriptions.js +1 -0
- package/dist/emblems/emblem.ids.d.ts +2 -2
- package/dist/emblems/emblem.ids.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,30 @@ All notable changes to this project are written here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.16.0] - 2026-10-21
|
|
10
|
+
|
|
11
|
+
A slotted plastic practice baseball joins the balls, drawn with the see-through holes of the pickleballs.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`ball:plastic-baseball-slotted`** (`BALL_PLASTIC_BASEBALL_SLOTTED`; "Plastic baseball, slotted"), the hollow white plastic practice baseball with eight oblong slots on one half and the other half solid (326 emblems, 118 balls). The size is a baseball's (73.8 mm); the slot count, the 19 mm slot length, the one perforated half and the wall of at most 3.2 mm are from the English Wikipedia article on the ball (read 2026-10-21); no source read gives a mass, so none is stated, and a slot's width, which is not given, is drawn at a third of its length (`docs/slotted-ball.md`). The package names no maker: the ball is generic, and the maker's registered trademark is in no id, name, document or picture (`NOTICE.md` cites the article without a link, because its address carries the mark).
|
|
16
|
+
- **Slots in `ball.holes.ts`**: `Holes` takes `long` and `dirs` to drill slots (half circles at the ends, a direction along the surface for each) instead of circles, and `slotRing` gives a slot's outline as points on the sphere; the same near holes, inside of the ball, far holes and mask as the pickleballs, so the page shows through where a near slot and a far one line up. The pickleballs are drawn as in 0.15.0.
|
|
17
|
+
- **`docs/slotted-ball.md`** with a still picture and a turning one (`pnpm screenshots`, sheet `slotted`; `pnpm animations`, scene `slotted-turn`), and tests in `test/holes.test.ts` and `e2e/holes.demo.ts` (a pixel through a near and a far slot is the page's own; the solid half has none).
|
|
18
|
+
|
|
19
|
+
## [0.15.0] - 2026-10-21
|
|
20
|
+
|
|
21
|
+
The pickleballs get real holes: cut through the shell, with the inside of the ball behind them, and the page showing through where two holes line up.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **`ball:pickleball-outdoor` and `ball:pickleball-indoor` have real holes** (new module `src/emblems/ball/ball.holes.ts`, taken only by the pickleballs). Each hole on the near side is cut out of the shell by a mask, so its shading, highlight and grain are cut with it; behind it is the inside of the hollow ball (the far shell's inner surface, darker, lit low and to the right) with the far holes cut out of it, so where a near hole and a far hole line up the SVG is transparent and the page shows through, on any background. A hole is a cylinder along the line to the centre: near the edge it is a thin ellipse and the bore's wall shows as a crescent, toned by the light, and the cut edge carries a soft shadow and a thin lit rim (the thickness of the shell). It turns with `ballFrame`, `emblemFrame` and `bindTurn`; every turn has ids of its own. The line style still draws a mark for each hole, and the hole counts and sizes are unchanged (40 small, 26 large). A pickleball's drawing is about 8 kB where it was 3.7 kB (about 1.7 to 2 kB gzipped); its bundle is 8.0 kB gzipped (the other balls' are unchanged).
|
|
26
|
+
- Every other ball with round marks (a golf ball's and a field hockey ball's dimples, a squash ball's dots) is drawn exactly as before: `BallSpec` gained an optional `holes` function that only the pickleballs set, and `test/holes.test.ts` holds the drawings of 0.14.0 by hash.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **`docs/pickleball.md`**, with pictures of both balls at rest and turned, light and dark, and a turning picture (`pnpm animations`, scene `pickleball-turn`; `pnpm screenshots`, sheet `pickleball`). The README shows the still picture under "The best of it", and the balls sheet is redrawn with the new hole.
|
|
31
|
+
- **`e2e/holes.demo.ts`**: in a real browser, a pixel seen through a near hole and the far hole behind it is transparent and equals the page's own on four page colours; the shell round a hole is solid; a turned ball shows the dark inside; a turning pickleball has open holes at some angle and a golf ball never does.
|
|
32
|
+
|
|
9
33
|
## [0.14.0] - 2026-10-21
|
|
10
34
|
|
|
11
35
|
The auto-turn can go either way, and the pictures and the demo are slower and wait for the pointer.
|
package/NOTICE.md
CHANGED
|
@@ -52,6 +52,7 @@ Each ball's `size.rule` names the rule; the table gives the document and where i
|
|
|
52
52
|
| `ball:gaelic-football` | GAA Official Guide Part 2, Rules of Specification, Rule 4.4(ii) | https://www.galwaygaa.ie/wp-content/uploads/2026/02/Official-Guide-Part-2.pdf |
|
|
53
53
|
| `ball:netball` | World Netball Rules of Netball, Rule 1 (Equipment: Ball), item 15 a-d | https://netballhamilton.org.nz/media/1997/world-netball-rules-book-2024.pdf |
|
|
54
54
|
| `ball:pickleball-outdoor`, `ball:pickleball-indoor` | USA Pickleball Equipment Standards Manual (Jan 2025, Revision 3.0), 2.D.1 Design, 2.D.3 Size, 2.D.4 Weight, 2.D.8 Design (holes); USA Pickleball 2026 Official Rulebook rule 3.C Ball Specifications | https://equipment.usapickleball.org/docs/Equipment-Standards-Manual.pdf |
|
|
55
|
+
| `ball:plastic-baseball-slotted` | English Wikipedia, the article on the hollow plastic practice ball with eight oblong holes (accessed 2026-10-21): hollow plastic, wall at most 1/8 in (3.2 mm), eight oblong holes of 0.75 in (19 mm) on one half only, about the size of a regulation baseball; the size is a baseball's, from Official Baseball Rules, Rule 3.01 The Ball | no link: the article is titled with the maker's registered trademark, which this package does not use |
|
|
55
56
|
| `ball:squash` and its coloured dots | World Squash 'Specifications for Squash Balls' (Recommended standards approved by the WSF; updated WSF AGM 2021, rebranded 2025), sections 1-3 and Notes 2-4 | https://www.worldsquash.sport/wp-content/uploads/2025/07/211127_Ball-Specifications.pdf |
|
|
56
57
|
| `ball:racquetball` | USA Racquetball Rules, Rule 2.2 Ball Specifications (a)-(b); Rule 2.3 Ball Selection | https://www.usaracquetball.com/play/rules/2-courts-and-equipment |
|
|
57
58
|
| `ball:lacrosse` | World Lacrosse Rules of Men's Field Lacrosse 2025-2027 (Ver 1.0), Section 2 Equipment, Rule 14 The Ball, 14.1 | https://www.bclacrosse.com/Referees%20and%20Officials/World%20Lacrosse%20Men's%20Field%20Rule%20Book.pdf |
|
package/README.md
CHANGED
|
@@ -70,7 +70,7 @@ The ball and the gear of every sport, trophies, medals, crests and the icon of e
|
|
|
70
70
|
</picture>
|
|
71
71
|
</p>
|
|
72
72
|
|
|
73
|
-
- **
|
|
73
|
+
- **118 balls and implements in 3D**, from the 32-panel soccer ball to the pucks and the curling stone, that roll as they turn ([gallery](./docs/gallery.md), [vintage and era-style balls](./docs/vintage-balls.md)).
|
|
74
74
|
|
|
75
75
|
<p align="center">
|
|
76
76
|
<picture>
|
|
@@ -79,6 +79,24 @@ The ball and the gear of every sport, trophies, medals, crests and the icon of e
|
|
|
79
79
|
</picture>
|
|
80
80
|
</p>
|
|
81
81
|
|
|
82
|
+
- **Pickleballs with real holes**: the holes are cut through the shell, so you see the dark inside of the ball and, where a near hole and a far one line up, the page itself ([pickleballs](./docs/pickleball.md)).
|
|
83
|
+
|
|
84
|
+
<p align="center">
|
|
85
|
+
<picture>
|
|
86
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/dougu-sports/main/docs/images/pickleball-dark.webp">
|
|
87
|
+
<img alt="Two pickleballs, the yellow outdoor ball with its 40 small holes above and the white indoor ball with its 26 large ones below, each at rest and at three turns: through each hole the dark inside of the ball shows, and where a hole in the near side lines up with one in the far side the background shows through." src="https://raw.githubusercontent.com/johnmorrisdotca/dougu-sports/main/docs/images/pickleball-light.webp" width="760">
|
|
88
|
+
</picture>
|
|
89
|
+
</p>
|
|
90
|
+
|
|
91
|
+
- **A slotted plastic practice baseball**, a hollow white ball with eight oblong slots on one half, drawn with the same see-through holes ([slotted ball](./docs/slotted-ball.md)).
|
|
92
|
+
|
|
93
|
+
<p align="center">
|
|
94
|
+
<picture>
|
|
95
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/johnmorrisdotca/dougu-sports/main/docs/images/slotted-dark.webp">
|
|
96
|
+
<img alt="The white slotted plastic ball four times: at rest with its ring of eight oblong slots, from the side with the background showing through two slots, from its pole, and from the solid half with no slot at all." src="https://raw.githubusercontent.com/johnmorrisdotca/dougu-sports/main/docs/images/slotted-light.webp" width="760">
|
|
97
|
+
</picture>
|
|
98
|
+
</p>
|
|
99
|
+
|
|
82
100
|
- **Trophies, medals, crests and the icon of every sport**, in metal, one line or flat colour, light and dark.
|
|
83
101
|
|
|
84
102
|
<p align="center">
|
|
@@ -92,7 +110,7 @@ The ball and the gear of every sport, trophies, medals, crests and the icon of e
|
|
|
92
110
|
|
|
93
111
|
- **On a phone**, and **turned by hand**: drag, arrow keys or the automatic turn ([turning](./docs/turning.md)).
|
|
94
112
|
|
|
95
|
-
> **Status: preview.**
|
|
113
|
+
> **Status: preview.** 326 emblems: 71 trophies, 6 awards, 6 medals, 4 crests, a pictogram for each of the 42 sports, 118 balls and implements drawn in 3D, 8 printed pucks ([docs/pucks.md](./docs/pucks.md)), 70 pieces of gear (among them the Japanese sports and budo, [docs/japanese-sports.md](./docs/japanese-sports.md)) and a championship pennant; [docs/layout.md](./docs/layout.md) says where each goes. All of it is drawn for this package: no art is copied from another project.
|
|
96
114
|
|
|
97
115
|
## In 30 seconds
|
|
98
116
|
|
|
@@ -120,7 +138,7 @@ Put the string in a page (`element.innerHTML = svg`), write it to a file, or sen
|
|
|
120
138
|
|
|
121
139
|
## Features
|
|
122
140
|
|
|
123
|
-
- **Equipment first (道具 is the word for it)**:
|
|
141
|
+
- **Equipment first (道具 is the word for it)**: 118 balls and implements drawn in 3D, from the 32-panel soccer ball to the 26, 18, 14, 12 and 6 panel constructions, vintage leather balls, era-style and shop-wall soccer balls, baseballs of other threads, volleyballs in national colours ([docs/vintage-balls.md](./docs/vintage-balls.md)), futsal, beach soccer and the pucks and stones, each with its official size, 8 printed pucks (a flag, a leaf, stars and stripes, a player's number, a made-up signature, your own picture: [docs/pucks.md](./docs/pucks.md)), and 42 pieces of gear (sticks, rackets, helmets, skates, nets, and the Japanese budo kit) drawn to match; see [docs/gallery.md](./docs/gallery.md).
|
|
124
142
|
- **Three styles** for every emblem: `metal` (polished metal: a gradient, a highlight and a soft rim of reflected light, edged in a darker tone of its own metal, with no heavy outline), `line` (one clean outline in the page's text colour, made to read at 14 pixels) and `color` (flat fills); see [Theming](#theming).
|
|
125
143
|
- **Size, tint, accent and theme** as options: a tint recolours the main part (a medal's metal, a crest's colour, a ball's patches), an accent the second colour (a ribbon, a crest's band, the pennants), a theme sets the ink for light, dark or either.
|
|
126
144
|
- **Turning**: `emblemFrame` and `ballFrame` return the emblem at an angle, in plain SVG: every emblem turns, a ball rolls, a cup keeps its outline and moves its light, and everything flat (gear, a bat, a crown, a sport's icon) flips like a coin; `bindTurn` lets a drag, the arrow keys or an auto-turn do the turning in a page; see [docs/turning.md](./docs/turning.md).
|
|
@@ -439,7 +457,7 @@ An emblem is a small object: `id`, `en` and `ja` names, a `source` (who drew it)
|
|
|
439
457
|
| `trophy` | Twenty-four trophies: ten that stand for a league's cup in a generic form (a tall banded cup, a ring of pennants round a baseball, a football on a stand, a ball over a net, a wide two-handled bowl, a globe held up by spiral figures, a gilt dish, a lidded cup with a pineapple, an urn, a gilded cup), plain cups, bowls and dishes, a plaque, a belt, a wreath, a rosette, a championship ring, a rafter banner, a phoenix-handled sumo cup and a championship banner | `src/emblems/trophy/` |
|
|
440
458
|
| `medal` | Gold, silver and bronze medals on a ribbon of five stripes, and a badge for each of the first three places | `src/emblems/medal/` |
|
|
441
459
|
| `crest` | Four generic crests, tinted by a team's colours, with its letters | `src/emblems/crest/` |
|
|
442
|
-
| `ball` |
|
|
460
|
+
| `ball` | 118 balls and implements, in 3D, each with its official size: soccer (in 32, 26, 18, 14, 12 and 6 panels, in three colourways, with futsal and beach soccer; [docs/soccer-balls.md](./docs/soccer-balls.md); and vintage leather, era-style and patterned balls, [docs/vintage-balls.md](./docs/vintage-balls.md)), basketball, baseball, tennis, rugby, the footballs, golf, the puck, the curling stone and the rest | `src/emblems/ball/` |
|
|
443
461
|
| `puck` | 8 printed pucks: the same puck with a print on its top face that turns with it (a flag and CANADA, a red leaf, stars and stripes, a player's name and number, a made-up signature, a souvenir), and a `face` option for any picture, emblem or flag code; [docs/pucks.md](./docs/pucks.md) | `src/emblems/ball/ball.puck.print.ts` |
|
|
444
462
|
| `gear` | 67 pieces of equipment: sticks, rackets, skates, a glove, a helmet, nets and posts, a javelin, starting blocks, and for the Japanese sports a war fan, a sumo belt, a bamboo sword, a kendo helmet, the judo suit (white and blue, laid flat and folded, and from behind with its back number), the belts of every grade (white to red, the red-and-white belt, the women's black belt and the two-colour belts) and the six steps of tying one, a long bow, an arrow and a karate suit | `src/emblems/gear/` |
|
|
445
463
|
| `sport` | One pictogram for each of the forty-two sports | `src/emblems/sport/` |
|
|
@@ -658,7 +676,7 @@ Bug reports and ideas go in the [issues](https://github.com/johnmorrisdotca/doug
|
|
|
658
676
|
|
|
659
677
|
## Changes
|
|
660
678
|
|
|
661
|
-
See [CHANGELOG.md](./CHANGELOG.md). 0.14.0 lets the auto-turn go either way (`direction: "clockwise"` or `"counterclockwise"`, `setDirection()`); 0.13.0 adds a pictogram for each of four combat sports, MMA (a cage), boxing (a glove), wrestling (two wrestlers on the mat) and professional wrestling (a ring with ropes), in the three styles (
|
|
679
|
+
See [CHANGELOG.md](./CHANGELOG.md). 0.16.0 adds a slotted plastic practice baseball (`ball:plastic-baseball-slotted`, 326 emblems: [docs/slotted-ball.md](./docs/slotted-ball.md)); 0.15.0 gives the pickleballs real holes, cut through the shell and drawn with the inside of the ball behind them, so the page shows through where two holes line up ([docs/pickleball.md](./docs/pickleball.md)); 0.14.0 lets the auto-turn go either way (`direction: "clockwise"` or `"counterclockwise"`, `setDirection()`); 0.13.0 adds a pictogram for each of four combat sports, MMA (a cage), boxing (a glove), wrestling (two wrestlers on the mat) and professional wrestling (a ring with ropes), in the three styles (326 emblems); 0.12.0 adds forty-seven named trophies, each a close likeness measured on a photograph (321 emblems); 0.11.0 gives the era soccer balls neutral ids (the old ones stay as aliases), new looks and a second 1980s ball (274 emblems); 0.10.0 adds a standalone ribbon and the nets and posts of sepak takraw, netball and teqball from their rulebooks' sizes (273 emblems); 0.9.0 lets the baseball, the softball and the classic soccer balls be painted and printed: solid and two-tone colours, a logo of your own wrapped onto the ball, stamped text, an original cursive word and a small mark, all turning with the ball ([docs/custom-balls.md](./docs/custom-balls.md)); 0.8.0 makes `bindTurn` light: it takes an emblem object and then needs no registry, so a turnable cup is about 9.4 kB gzipped instead of about 81 kB, and an id loads the registry on demand; 0.7.3 turns the build, docs and picture scripts, the browser tests and the demo's source from JavaScript into TypeScript, with no change to the package; 0.7.2 makes every docs page single-language (a page in Japanese beside each page that had Japanese words in it, and a test that holds them apart), with no change to the pictures; 0.7.1 puts real countries (Canada, Japan) in the crest and puck examples in place of made-up teams, with no change to the code; 0.7.0 gives the national volleyballs layouts that tell them apart (Japan a crimson band, Poland white above and red below, the USA a navy field), strengthens the 2010-style grooved soccer ball, and adds six pictures of how the judo belt is tied, `gear:obi-step-1` to `gear:obi-step-6` (269 emblems: [docs/obi-steps.md](./docs/obi-steps.md)); 0.6.0 gives the judo suit and the karate suit their sleeves (a judogi has no short ones: they reach the wrist) and adds the judogi seen from behind with the IJF-style back number, a family name and a country code on a patch, with a `backnumber` option (269 emblems: [docs/judogi-back.md](./docs/judogi-back.md)); 0.5.1 redraws the judo suit, the belt and the football pictograms and adds the blue and folded suits and the belts of every grade (261 emblems: [docs/japanese-sports.md](./docs/japanese-sports.md)); 0.5.0 adds fifty balls: vintage leather soccer balls, era-style and shop-wall soccer balls, baseballs of other threads and volleyballs in national colours, with a `colors` option (244 emblems: [docs/vintage-balls.md](./docs/vintage-balls.md)); 0.4.0 adds eight printed pucks and a `face` option (194 emblems: [docs/pucks.md](./docs/pucks.md)); 0.3.0 adds nineteen soccer balls (26, 18, 14, 12 and 6 panels, winter orange and high-visibility yellow, futsal and beach soccer: 186 emblems); 0.2.1 draws every ball and implement to the rulebook's proportions; 0.2.0 is 167 emblems, every one drawn here, with the Japanese sports, engraving, a turn for every emblem and the compose helpers; 0.1.0 brought the first full set of 148; 0.0.1 was the first preview.
|
|
662
680
|
|
|
663
681
|
## Credits
|
|
664
682
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Piece, type PieceSize, type PrintOptions, type PrintRenderer, type ResolvedOptions, type ResolvedPaint } from "./ball.core.ts";
|
|
2
|
+
import type { HoleLayers } from "./ball.holes.ts";
|
|
2
3
|
import { type M3, type V3 } from "./ball.math.ts";
|
|
3
4
|
/** How a ball takes the light. */
|
|
4
5
|
export interface Material {
|
|
@@ -121,6 +122,11 @@ export interface BallSpec {
|
|
|
121
122
|
at?: V3;
|
|
122
123
|
/** The fraction of the box's radius the ball takes (1 by default): a hammer's head is small, to leave room for its wire. */
|
|
123
124
|
fit?: number;
|
|
125
|
+
/**
|
|
126
|
+
* A ball with real holes (a pickleball), drilled through its shell: each near hole is cut out and shows the inside of the ball, and where a near and a far hole line up the page shows through.
|
|
127
|
+
* It is a function (`drillHoles` in ball.holes.ts, bound to the hole centres) so that a ball without holes does not carry the code. The line style does not call it (a `draw` that wants marks there draws them).
|
|
128
|
+
*/
|
|
129
|
+
holes?: (s: Surface, id: string, base: string, shape: (attrs: string) => string, minWidth: number) => HoleLayers;
|
|
124
130
|
/** What is attached to the ball and sticks out of it (a hammer's wire and handle): drawn behind the ball or in front of it, by what is nearer to you. */
|
|
125
131
|
attach?: (s: Surface, base: string) => {
|
|
126
132
|
behind: string;
|
|
@@ -363,11 +363,13 @@ export function drawBall(title, key, spec, opts, turn, turning) {
|
|
|
363
363
|
(gr === undefined
|
|
364
364
|
? ""
|
|
365
365
|
: grainDef(id, gr.f, gr.a, gr.seed));
|
|
366
|
-
const
|
|
366
|
+
const hol = spec.holes?.(surface, id, base, shape, minWidth);
|
|
367
|
+
const inner = `<g clip-path="url(#${id}c)"${gr === undefined ? "" : ` filter="url(#${id}n)"`}>${shape(`fill="${ground ?? spec.ground ?? base}"`)}${layers}${hol?.edge ?? ""}</g>`;
|
|
367
368
|
const metal = m.metal === true ? shape(`fill="url(#${id}m)"`) : "";
|
|
368
369
|
const overlays = shape(`fill="url(#${id}d)"`) + metal + shape(`fill="url(#${id}b)"`) + shape(`fill="url(#${id}h)"`);
|
|
369
370
|
const at = spec.attach?.(surface, base);
|
|
370
|
-
|
|
371
|
+
const shell = hol?.mask === undefined ? `${inner}${overlays}` : `<g mask="url(#${hol.mask})">${inner}${overlays}</g>`;
|
|
372
|
+
return wrapPiece({ title, size: opts.size, theme: opts.theme, defs: defs + (hol?.defs ?? "") + metalDef(id, m.metal === true), body: `${at?.behind ?? ""}${hol?.behind ?? ""}${shell}${at?.front ?? ""}` });
|
|
371
373
|
}
|
|
372
374
|
/** A ball's label area as a surface sees it: the middle, the right-hand and the upward direction, orthogonal, and how far it reaches. */
|
|
373
375
|
function homeOf(spec) {
|
|
@@ -2,6 +2,7 @@ import { type BallDef } from "./ball.engine.ts";
|
|
|
2
2
|
import { type V3 } from "./ball.math.ts";
|
|
3
3
|
import type { Piece } from "./ball.core.ts";
|
|
4
4
|
import type { BallSpec } from "./ball.engine.ts";
|
|
5
|
+
import type { Drill } from "./ball.holes.ts";
|
|
5
6
|
export interface DottedOptions {
|
|
6
7
|
id: string;
|
|
7
8
|
en: string;
|
|
@@ -19,6 +20,8 @@ export interface DottedOptions {
|
|
|
19
20
|
mark?: string;
|
|
20
21
|
/** A lit rim on each mark (not for a dimple pattern of two hundred, which is large enough already). */
|
|
21
22
|
light?: boolean;
|
|
23
|
+
/** Real holes through the shell, not marks on it (`holeLayers` from ball.holes.ts, taken by the pickleball only): the near ones are cut out and show the inside of the ball, and where two line up the page shows through. The line style still draws marks. */
|
|
24
|
+
hollow?: Drill;
|
|
22
25
|
/** Turns the spread, so a ball does not show its spiral's pole straight on. */
|
|
23
26
|
phase?: number;
|
|
24
27
|
}
|
|
@@ -13,8 +13,11 @@ export function dottedBall(o) {
|
|
|
13
13
|
mat: o.mat,
|
|
14
14
|
draw: (s, base) => {
|
|
15
15
|
const mark = o.mark ?? mix(base, -0.55);
|
|
16
|
+
if (o.hollow !== undefined && !s.line)
|
|
17
|
+
return "";
|
|
16
18
|
return s.dots(centres, o.radius, mark, { opacity: o.depth ?? 0.55, ink: true, light: o.light ?? true });
|
|
17
19
|
},
|
|
20
|
+
holes: o.hollow === undefined ? undefined : (s, id, base, shape, minWidth) => o.hollow(s, id, { centres, radius: o.radius }, base, shape, minWidth),
|
|
18
21
|
};
|
|
19
22
|
return defineBall({ id: o.id, en: o.en, ja: o.ja, spec, size: o.size });
|
|
20
23
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Surface } from "./ball.engine.ts";
|
|
2
|
+
import { type V3 } from "./ball.math.ts";
|
|
3
|
+
/**
|
|
4
|
+
* Where a ball is drilled: the hole centres on the unit sphere, a hole's radius as the angle of its cap in radians, and the shell's thickness as a fraction of the ball's radius (0.05 by default).
|
|
5
|
+
* With `long` the holes are slots instead of circles: `radius` is then half the width of a slot, `long` is half its length (both in radians, `long` at least `radius`), and `dirs` has, for each
|
|
6
|
+
* centre, a direction along the ball's surface at that centre (it is made to lie in the surface) that the slot's length runs along. The ends of a slot are half circles.
|
|
7
|
+
*/
|
|
8
|
+
export interface Holes {
|
|
9
|
+
centres: readonly V3[];
|
|
10
|
+
radius: number;
|
|
11
|
+
wall?: number;
|
|
12
|
+
long?: number;
|
|
13
|
+
dirs?: readonly V3[];
|
|
14
|
+
}
|
|
15
|
+
/** What `holeLayers` makes: the definitions, the inside of the ball (drawn first), the edges drawn on the shell, and the mask that cuts the near holes out of everything on the shell, if there is one. */
|
|
16
|
+
export interface HoleLayers {
|
|
17
|
+
defs: string;
|
|
18
|
+
behind: string;
|
|
19
|
+
edge: string;
|
|
20
|
+
mask: string | undefined;
|
|
21
|
+
}
|
|
22
|
+
/** The slot's outline as points on the sphere (or `depth` below it: the bore is a cylinder along the line to the ball's centre), for a slot with this middle and this direction along its length. */
|
|
23
|
+
export declare function slotRing(m: V3, dir: V3, half: number, long: number, depth?: number): V3[];
|
|
24
|
+
/** The signature of `holeLayers`, which a ball is handed so that its own module is the only one that carries the code. */
|
|
25
|
+
export type Drill = (s: Surface, id: string, holes: Holes, base: string, shape: (attrs: string) => string, minWidth: number) => HoleLayers;
|
|
26
|
+
export declare const holeLayers: Drill;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { hashOf, mix, num } from "./ball.core.js";
|
|
2
|
+
import { add, basis, cross, ellipseOf, mul, norm } from "./ball.math.js";
|
|
3
|
+
/** The outline of a slot as points in the plane that touches the sphere at its middle, `a` along the length and `b` across: two straight sides and a half circle at each end. */
|
|
4
|
+
function capsule(half, long) {
|
|
5
|
+
const out = [];
|
|
6
|
+
const run = long - half;
|
|
7
|
+
const steps = 6;
|
|
8
|
+
for (let i = 0; i <= steps; i++) {
|
|
9
|
+
const t = -Math.PI / 2 + (Math.PI * i) / steps;
|
|
10
|
+
out.push([run + half * Math.cos(t), half * Math.sin(t)]);
|
|
11
|
+
}
|
|
12
|
+
for (let i = 0; i <= steps; i++) {
|
|
13
|
+
const t = Math.PI / 2 + (Math.PI * i) / steps;
|
|
14
|
+
out.push([-run + half * Math.cos(t), half * Math.sin(t)]);
|
|
15
|
+
}
|
|
16
|
+
return out;
|
|
17
|
+
}
|
|
18
|
+
/** A polygon as a path: the first point, then the steps between rounded points (so the outline does not drift), to a tenth of a unit of the box. */
|
|
19
|
+
function polygon(pts) {
|
|
20
|
+
const r = (v) => Math.round(v * 10) / 10;
|
|
21
|
+
let x = r(pts[0][0]), y = r(pts[0][1]);
|
|
22
|
+
let out = `M${num(x)} ${num(y)}l`;
|
|
23
|
+
for (let i = 1; i < pts.length; i++) {
|
|
24
|
+
const nx = r(pts[i][0]), ny = r(pts[i][1]);
|
|
25
|
+
out += `${i === 1 ? "" : " "}${num(nx - x)} ${num(ny - y)}`;
|
|
26
|
+
x = nx;
|
|
27
|
+
y = ny;
|
|
28
|
+
}
|
|
29
|
+
return `${out}z`;
|
|
30
|
+
}
|
|
31
|
+
/** The slot's outline as points on the sphere (or `depth` below it: the bore is a cylinder along the line to the ball's centre), for a slot with this middle and this direction along its length. */
|
|
32
|
+
export function slotRing(m, dir, half, long, depth = 0) {
|
|
33
|
+
const t1 = norm(add(dir, mul(m, -(dir[0] * m[0] + dir[1] * m[1] + dir[2] * m[2]))));
|
|
34
|
+
const t2 = cross(m, t1);
|
|
35
|
+
return capsule(half, long).map(([a, b]) => {
|
|
36
|
+
const r = Math.hypot(a, b) || 1e-9;
|
|
37
|
+
const k = Math.sin(r) / r;
|
|
38
|
+
return add(mul(m, Math.cos(r) - depth), add(mul(t1, a * k), mul(t2, b * k)));
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
/** The slot's outline `depth` below the surface, as the polygon it makes on the screen. */
|
|
42
|
+
function slot(s, m, dir, holes, depth) {
|
|
43
|
+
const pts = slotRing(m, dir, holes.radius, holes.long ?? holes.radius, depth).map((p) => {
|
|
44
|
+
const q = s.project(p);
|
|
45
|
+
return [q[0], q[1]];
|
|
46
|
+
});
|
|
47
|
+
const c = s.project(mul(m, 1 - depth));
|
|
48
|
+
return { d: polygon(pts), x: c[0], y: c[1], facing: s.facing(m) };
|
|
49
|
+
}
|
|
50
|
+
/** The circle of the hole's bore at `depth` below the surface (0 on the outside), as the ellipse it makes on the screen; undefined where it is too thin to draw. */
|
|
51
|
+
function bore(s, m, radius, depth) {
|
|
52
|
+
const [t1, t2] = basis(m);
|
|
53
|
+
const sr = Math.sin(radius), cr = Math.cos(radius) - depth;
|
|
54
|
+
const c = s.project(mul(m, cr));
|
|
55
|
+
const o = s.project([0, 0, 0]);
|
|
56
|
+
const pa = s.project(mul(t1, sr));
|
|
57
|
+
const pb = s.project(mul(t2, sr));
|
|
58
|
+
const da = [pa[0] - o[0], pa[1] - o[1]];
|
|
59
|
+
const db = [pb[0] - o[0], pb[1] - o[1]];
|
|
60
|
+
const { rx, ry, angle } = ellipseOf([[da[0], db[0], 0], [da[1], db[1], 0]]);
|
|
61
|
+
if (rx < 0.05)
|
|
62
|
+
return undefined;
|
|
63
|
+
const ry2 = Math.max(ry, 0.05);
|
|
64
|
+
const ax = Math.cos(angle) * rx, ay = Math.sin(angle) * rx;
|
|
65
|
+
const arcs = `a${num(rx)} ${num(ry2)} ${num((angle * 180) / Math.PI, 0)} 1 0`;
|
|
66
|
+
return { d: `M${num(c[0] + ax)} ${num(c[1] + ay)}${arcs}${num(-2 * ax)} ${num(-2 * ay)}${arcs}${num(2 * ax)} ${num(2 * ay)}`, x: c[0], y: c[1], facing: s.facing(m) };
|
|
67
|
+
}
|
|
68
|
+
/** A hole's opening at a depth: a circle's ellipse, or a slot's outline. */
|
|
69
|
+
const opening = (s, holes, i, depth) => {
|
|
70
|
+
const m = holes.centres[i];
|
|
71
|
+
const dir = holes.dirs?.[i];
|
|
72
|
+
return holes.long !== undefined && dir !== undefined ? slot(s, m, dir, holes, depth) : bore(s, m, holes.radius, depth);
|
|
73
|
+
};
|
|
74
|
+
/** The light comes from the upper left, as it does everywhere else in the engine. */
|
|
75
|
+
const LIGHT = [-0.62, -0.78];
|
|
76
|
+
/** The tones a wall is drawn in, darkest first, as amounts of the ball's colour mixed toward black. */
|
|
77
|
+
const TONES = [-0.6, -0.45, -0.3, -0.15];
|
|
78
|
+
export const holeLayers = (s, id, holes, base, shape, minWidth) => {
|
|
79
|
+
const thick = holes.wall ?? 0.05;
|
|
80
|
+
const front = [];
|
|
81
|
+
const backOut = [];
|
|
82
|
+
const backIn = [];
|
|
83
|
+
for (let i = 0; i < holes.centres.length; i++) {
|
|
84
|
+
const f = s.facing(holes.centres[i]);
|
|
85
|
+
if (f >= 0.08) {
|
|
86
|
+
const out = opening(s, holes, i, 0);
|
|
87
|
+
if (out !== undefined)
|
|
88
|
+
front.push({ out, inn: opening(s, holes, i, thick) });
|
|
89
|
+
}
|
|
90
|
+
else if (f <= -0.08) {
|
|
91
|
+
const out = opening(s, holes, i, 0);
|
|
92
|
+
const inn = opening(s, holes, i, thick);
|
|
93
|
+
if (out !== undefined && inn !== undefined) {
|
|
94
|
+
backOut.push(out);
|
|
95
|
+
backIn.push(inn);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (front.length === 0 && backOut.length === 0)
|
|
100
|
+
return { defs: "", behind: "", edge: "", mask: undefined };
|
|
101
|
+
const frontPath = front.map((h) => h.out.d).join("");
|
|
102
|
+
const backOutPath = backOut.map((o) => o.d).join("");
|
|
103
|
+
const backInPath = backIn.map((o) => o.d).join("");
|
|
104
|
+
const key = hashOf(frontPath + "|" + backOutPath + "|" + backInPath);
|
|
105
|
+
// The inside of the ball: lit a little where the light that comes through the near holes lands (low and to the right), dark toward the edge.
|
|
106
|
+
let defs = `<radialGradient id="${id}i" cx=".62" cy=".66" r=".62"><stop offset="0" stop-color="${mix(base, -0.36)}"/><stop offset="1" stop-color="${mix(base, -0.72)}"/></radialGradient>`;
|
|
107
|
+
let disc = shape(`fill="url(#${id}i)"`);
|
|
108
|
+
if (backOut.length > 0) {
|
|
109
|
+
// A far hole is open where its inner opening and its outer opening overlap: the bore leans away from you, so a hole near the far edge is a slit.
|
|
110
|
+
defs += `<clipPath id="${id}o${key}"><path d="${backOutPath}"/></clipPath><mask id="${id}b${key}" maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100"><rect width="100" height="100" fill="#fff"/><path d="${backInPath}" fill="#000" clip-path="url(#${id}o${key})"/></mask>`;
|
|
111
|
+
disc = shape(`fill="url(#${id}i)" mask="url(#${id}b${key})"`);
|
|
112
|
+
}
|
|
113
|
+
// The wall of each near hole: what is inside the outer opening and outside the inner one (the part of the bore that faces you), toned by whether it faces the light and how near the edge it is.
|
|
114
|
+
const o = s.project([0, 0, 0]);
|
|
115
|
+
const buckets = TONES.map(() => []);
|
|
116
|
+
for (const h of front) {
|
|
117
|
+
if (h.inn === undefined)
|
|
118
|
+
continue;
|
|
119
|
+
const dx = h.out.x - o[0], dy = h.out.y - o[1];
|
|
120
|
+
const d = Math.hypot(dx, dy) || 1;
|
|
121
|
+
// The wall you see is the one on the far side of the hole, facing the middle of the ball on the screen.
|
|
122
|
+
const lit = (-dx / d) * LIGHT[0] + (-dy / d) * LIGHT[1];
|
|
123
|
+
const k = -0.3 + 0.2 * lit - 0.25 * (1 - h.out.facing);
|
|
124
|
+
let best = 0;
|
|
125
|
+
for (let i = 1; i < TONES.length; i++)
|
|
126
|
+
if (Math.abs(TONES[i] - k) < Math.abs(TONES[best] - k))
|
|
127
|
+
best = i;
|
|
128
|
+
buckets[best].push(h.out.d + h.inn.d);
|
|
129
|
+
}
|
|
130
|
+
const walls = buckets.map((b, i) => (b.length === 0 ? "" : `<path d="${b.join("")}" fill="${mix(base, TONES[i])}" fill-rule="evenodd"/>`)).join("");
|
|
131
|
+
const behind = `<g clip-path="url(#${id}c)">${disc}${walls}</g>`;
|
|
132
|
+
if (front.length === 0)
|
|
133
|
+
return { defs, behind, edge: "", mask: undefined };
|
|
134
|
+
// The outline of the near holes is written once and used three times.
|
|
135
|
+
defs += `<path id="${id}f${key}" d="${frontPath}"/><mask id="${id}k${key}" maskUnits="userSpaceOnUse" x="0" y="0" width="100" height="100"><rect width="100" height="100" fill="#fff"/><use href="#${id}f${key}" fill="#000"/></mask>`;
|
|
136
|
+
// On the shell, round each cut: a soft shadow where the plastic turns in, and a thin lit edge (the cut face of the shell). Half of each stroke lies inside the cut and is masked away.
|
|
137
|
+
const edge = `<use href="#${id}f${key}" fill="none" stroke="${mix(base, -0.6)}" stroke-width="${num(Math.max(1.1, minWidth * 0.8), 2)}" opacity=".22"/>` +
|
|
138
|
+
`<use href="#${id}f${key}" fill="none" stroke="${mix(base, 0.5)}" stroke-width="${num(Math.max(0.3, minWidth * 0.3), 2)}" opacity=".5"/>`;
|
|
139
|
+
return { defs, behind, edge, mask: `${id}k${key}` };
|
|
140
|
+
};
|
|
@@ -14,6 +14,7 @@ import { BALL_HAMMER } from "./ball.hammer.js";
|
|
|
14
14
|
import { BALL_HANDBALL } from "./ball.handball.js";
|
|
15
15
|
import { BALL_PADEL } from "./ball.padel.js";
|
|
16
16
|
import { BALL_PICKLEBALL_OUTDOOR, BALL_PICKLEBALL_INDOOR } from "./ball.pickleball.js";
|
|
17
|
+
import { BALL_PLASTIC_BASEBALL_SLOTTED } from "./ball.plastic.js";
|
|
17
18
|
import { BALL_PUCK } from "./ball.puck.js";
|
|
18
19
|
import { PUCKS } from "./ball.puck.print.js";
|
|
19
20
|
import { BALL_BASEBALL, BALL_SOCCER, BALL_SOCCER_COLOUR, BALL_SOCCER_ORANGE, BALL_SOCCER_YELLOW, BALL_SOFTBALL } from "./ball.printable.js";
|
|
@@ -36,7 +37,7 @@ import { BALL_TEQBALL } from "./ball.teqball.js";
|
|
|
36
37
|
import { BALL_VOLLEYBALL, BALL_VOLLEYBALL_8, BALL_BEACH_VOLLEYBALL } from "./ball.volleyball.js";
|
|
37
38
|
import { BALL_WATER_POLO } from "./ball.waterpolo.js";
|
|
38
39
|
/** Every ball, in the order a gallery shows them. */
|
|
39
|
-
export const BALLS = [BALL_SOCCER, BALL_SOCCER_COLOUR, BALL_SOCCER_26, BALL_SOCCER_18, BALL_SOCCER_14, BALL_SOCCER_12, BALL_SOCCER_6, BALL_SOCCER_ORANGE, BALL_SOCCER_26_ORANGE, BALL_SOCCER_18_ORANGE, BALL_SOCCER_14_ORANGE, BALL_SOCCER_12_ORANGE, BALL_SOCCER_6_ORANGE, BALL_SOCCER_YELLOW, BALL_SOCCER_26_YELLOW, BALL_SOCCER_18_YELLOW, BALL_SOCCER_14_YELLOW, BALL_SOCCER_12_YELLOW, BALL_SOCCER_6_YELLOW, BALL_FUTSAL, BALL_BEACH_SOCCER, BALL_SOCCER_1870_HAND_STITCHED, BALL_SOCCER_1900_LACED, BALL_SOCCER_1930_18_PANEL, BALL_SOCCER_1950_12_PANEL, BALL_SOCCER_1960_32_PANEL_LEATHER, BALL_SOCCER_RETRO_PENTAGONS, BALL_SOCCER_RETRO_LEAVES, BALL_SOCCER_RETRO_ROSETTE, BALL_SOCCER_RETRO_STAR, BALL_SOCCER_RETRO_PINWHEEL, BALL_SOCCER_RETRO_KITES, BALL_SOCCER_14_PANEL_DOUBLE_BORDER, BALL_SOCCER_8_PANEL_PLAIN, BALL_SOCCER_6_PANEL_BANDS, BALL_SOCCER_6_PANEL_DIAMONDS, BALL_SOCCER_20_PANEL_DOTS, BALL_SOCCER_TRAINING_HIGH_VIS, BALL_SOCCER_STARS_BLUE, BALL_SOCCER_STARS_RED, BALL_SOCCER_STARS_NIGHT, BALL_SOCCER_HEXAGONS_CYAN, BALL_SOCCER_HEXAGONS_MAGENTA, BALL_SOCCER_HEXAGONS_LIME, BALL_SOCCER_FLAMES_FIRE, BALL_SOCCER_FLAMES_ICE, BALL_SOCCER_FLAMES_TOXIC, BALL_SOCCER_CHEVRONS_RED, BALL_SOCCER_CHEVRONS_GREEN, BALL_SOCCER_CHEVRONS_BLUE, BALL_SOCCER_SWIRL_BLUE, BALL_SOCCER_SWIRL_RED, BALL_SOCCER_SWIRL_TEAL, BALL_SOCCER_METALLIC_GOLD, BALL_SOCCER_METALLIC_SILVER, BALL_SOCCER_METALLIC_COBALT, BALL_TEQBALL, BALL_BASKETBALL, BALL_BASKETBALL_6, BALL_BASKETBALL_3X3, BALL_BASEBALL, BALL_SOFTBALL, BALL_BASEBALL_LEMON_PEEL, BALL_BASEBALL_RED_BLUE, BALL_BASEBALL_BLACK_RED, BALL_BASEBALL_VINTAGE_LEATHER, BALL_SOFTBALL_11_OPTIC, BALL_TENNIS, BALL_PADEL, BALL_SLIOTAR, BALL_VOLLEYBALL, BALL_VOLLEYBALL_8, BALL_BEACH_VOLLEYBALL, BALL_VOLLEYBALL_COLOURS, BALL_VOLLEYBALL_BRAZIL, BALL_VOLLEYBALL_JAPAN, BALL_VOLLEYBALL_CANADA, BALL_VOLLEYBALL_USA, BALL_VOLLEYBALL_ITALY, BALL_VOLLEYBALL_POLAND, BALL_VOLLEYBALL_FRANCE, BALL_VOLLEYBALL_SERBIA, BALL_VOLLEYBALL_NETHERLANDS, BALL_VOLLEYBALL_GERMANY, BALL_CRICKET_RED, BALL_CRICKET_WHITE, BALL_CRICKET_PINK, BALL_FOOTBALL, BALL_FOOTBALL_CFL, BALL_FOOTBALL_IFAF, BALL_RUGBY, BALL_AFL, BALL_GAELIC_FOOTBALL, BALL_NETBALL, BALL_PICKLEBALL_OUTDOOR, BALL_PICKLEBALL_INDOOR, BALL_SQUASH_DOUBLE_YELLOW, BALL_SQUASH_YELLOW, BALL_SQUASH_GREEN, BALL_SQUASH_RED, BALL_SQUASH_BLUE, BALL_RACQUETBALL, BALL_LACROSSE, BALL_FIELD_HOCKEY, BALL_TABLE_TENNIS, BALL_HANDBALL, BALL_WATER_POLO, BALL_GOLF, BALL_PUCK, BALL_CURLING_STONE, BALL_SHOT, BALL_DISCUS, BALL_HAMMER, BALL_SEPAK_TAKRAW, BALL_ROUNDNET, BALL_SHUTTLECOCK_FEATHER, BALL_SHUTTLECOCK_NYLON];
|
|
40
|
+
export const BALLS = [BALL_SOCCER, BALL_SOCCER_COLOUR, BALL_SOCCER_26, BALL_SOCCER_18, BALL_SOCCER_14, BALL_SOCCER_12, BALL_SOCCER_6, BALL_SOCCER_ORANGE, BALL_SOCCER_26_ORANGE, BALL_SOCCER_18_ORANGE, BALL_SOCCER_14_ORANGE, BALL_SOCCER_12_ORANGE, BALL_SOCCER_6_ORANGE, BALL_SOCCER_YELLOW, BALL_SOCCER_26_YELLOW, BALL_SOCCER_18_YELLOW, BALL_SOCCER_14_YELLOW, BALL_SOCCER_12_YELLOW, BALL_SOCCER_6_YELLOW, BALL_FUTSAL, BALL_BEACH_SOCCER, BALL_SOCCER_1870_HAND_STITCHED, BALL_SOCCER_1900_LACED, BALL_SOCCER_1930_18_PANEL, BALL_SOCCER_1950_12_PANEL, BALL_SOCCER_1960_32_PANEL_LEATHER, BALL_SOCCER_RETRO_PENTAGONS, BALL_SOCCER_RETRO_LEAVES, BALL_SOCCER_RETRO_ROSETTE, BALL_SOCCER_RETRO_STAR, BALL_SOCCER_RETRO_PINWHEEL, BALL_SOCCER_RETRO_KITES, BALL_SOCCER_14_PANEL_DOUBLE_BORDER, BALL_SOCCER_8_PANEL_PLAIN, BALL_SOCCER_6_PANEL_BANDS, BALL_SOCCER_6_PANEL_DIAMONDS, BALL_SOCCER_20_PANEL_DOTS, BALL_SOCCER_TRAINING_HIGH_VIS, BALL_SOCCER_STARS_BLUE, BALL_SOCCER_STARS_RED, BALL_SOCCER_STARS_NIGHT, BALL_SOCCER_HEXAGONS_CYAN, BALL_SOCCER_HEXAGONS_MAGENTA, BALL_SOCCER_HEXAGONS_LIME, BALL_SOCCER_FLAMES_FIRE, BALL_SOCCER_FLAMES_ICE, BALL_SOCCER_FLAMES_TOXIC, BALL_SOCCER_CHEVRONS_RED, BALL_SOCCER_CHEVRONS_GREEN, BALL_SOCCER_CHEVRONS_BLUE, BALL_SOCCER_SWIRL_BLUE, BALL_SOCCER_SWIRL_RED, BALL_SOCCER_SWIRL_TEAL, BALL_SOCCER_METALLIC_GOLD, BALL_SOCCER_METALLIC_SILVER, BALL_SOCCER_METALLIC_COBALT, BALL_TEQBALL, BALL_BASKETBALL, BALL_BASKETBALL_6, BALL_BASKETBALL_3X3, BALL_BASEBALL, BALL_SOFTBALL, BALL_BASEBALL_LEMON_PEEL, BALL_BASEBALL_RED_BLUE, BALL_BASEBALL_BLACK_RED, BALL_BASEBALL_VINTAGE_LEATHER, BALL_SOFTBALL_11_OPTIC, BALL_TENNIS, BALL_PADEL, BALL_SLIOTAR, BALL_VOLLEYBALL, BALL_VOLLEYBALL_8, BALL_BEACH_VOLLEYBALL, BALL_VOLLEYBALL_COLOURS, BALL_VOLLEYBALL_BRAZIL, BALL_VOLLEYBALL_JAPAN, BALL_VOLLEYBALL_CANADA, BALL_VOLLEYBALL_USA, BALL_VOLLEYBALL_ITALY, BALL_VOLLEYBALL_POLAND, BALL_VOLLEYBALL_FRANCE, BALL_VOLLEYBALL_SERBIA, BALL_VOLLEYBALL_NETHERLANDS, BALL_VOLLEYBALL_GERMANY, BALL_CRICKET_RED, BALL_CRICKET_WHITE, BALL_CRICKET_PINK, BALL_FOOTBALL, BALL_FOOTBALL_CFL, BALL_FOOTBALL_IFAF, BALL_RUGBY, BALL_AFL, BALL_GAELIC_FOOTBALL, BALL_NETBALL, BALL_PICKLEBALL_OUTDOOR, BALL_PICKLEBALL_INDOOR, BALL_PLASTIC_BASEBALL_SLOTTED, BALL_SQUASH_DOUBLE_YELLOW, BALL_SQUASH_YELLOW, BALL_SQUASH_GREEN, BALL_SQUASH_RED, BALL_SQUASH_BLUE, BALL_RACQUETBALL, BALL_LACROSSE, BALL_FIELD_HOCKEY, BALL_TABLE_TENNIS, BALL_HANDBALL, BALL_WATER_POLO, BALL_GOLF, BALL_PUCK, BALL_CURLING_STONE, BALL_SHOT, BALL_DISCUS, BALL_HAMMER, BALL_SEPAK_TAKRAW, BALL_ROUNDNET, BALL_SHUTTLECOCK_FEATHER, BALL_SHUTTLECOCK_NYLON];
|
|
40
41
|
/** The id of every ball: `"ball:soccer"`, `"ball:cricket-red"`. */
|
|
41
42
|
export const BALL_IDS = BALLS.map((b) => b.id);
|
|
42
43
|
const TABLE = new Map([...BALLS, ...PUCKS].map((b) => [b.id, b]));
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
// Pickleball: a perforated plastic ball. The outdoor ball has 40 small holes; the indoor ball has 26 larger ones (the rulebook gives 26 to 40 holes; the split is how balls are sold).
|
|
2
2
|
import { dottedBall } from "./ball.family.dotted.js";
|
|
3
|
+
import { holeLayers } from "./ball.holes.js";
|
|
3
4
|
export const BALL_PICKLEBALL_OUTDOOR = /* @__PURE__ */ dottedBall({
|
|
4
5
|
id: "ball:pickleball-outdoor",
|
|
5
6
|
en: "Pickleball, outdoor",
|
|
@@ -11,6 +12,7 @@ export const BALL_PICKLEBALL_OUTDOOR = /* @__PURE__ */ dottedBall({
|
|
|
11
12
|
mat: { gloss: 0.55, shade: "#4a5008", grain: { f: 1.4, a: 0.1 } },
|
|
12
13
|
mark: "#454b0e",
|
|
13
14
|
depth: 0.75,
|
|
15
|
+
hollow: holeLayers,
|
|
14
16
|
});
|
|
15
17
|
export const BALL_PICKLEBALL_INDOOR = /* @__PURE__ */ dottedBall({
|
|
16
18
|
id: "ball:pickleball-indoor",
|
|
@@ -23,4 +25,5 @@ export const BALL_PICKLEBALL_INDOOR = /* @__PURE__ */ dottedBall({
|
|
|
23
25
|
mat: { gloss: 0.6, shade: "#3a3a40", grain: { f: 1.4, a: 0.08 } },
|
|
24
26
|
mark: "#3d3d44",
|
|
25
27
|
depth: 0.7,
|
|
28
|
+
hollow: holeLayers,
|
|
26
29
|
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const BALL_PLASTIC_BASEBALL_SLOTTED: import("./ball.core.ts").Piece<import("./ball.engine.ts").BallSpec>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// The slotted plastic practice baseball: a hollow white plastic ball the size of a baseball, with eight oblong slots on one half and the other half solid. The figures are from the English Wikipedia
|
|
2
|
+
// article on the ball (accessed 2026-10-21): hollow resilient plastic, a wall no more than 1/8 inch (3.2 mm) thick, eight oblong holes of 0.75 inch (19 mm), on one half only, about the size of a regulation
|
|
3
|
+
// baseball. The holes are real, as a pickleball's are (ball.holes.ts): the near ones are cut out of the shell and show the inside of the ball, and where a near slot and a far one line up the page shows through.
|
|
4
|
+
// No maker's name is in this package: it is a generic ball.
|
|
5
|
+
import { defineBall } from "./ball.engine.js";
|
|
6
|
+
import { holeLayers, slotRing } from "./ball.holes.js";
|
|
7
|
+
/** The axis of the perforated half: its pole, the middle of the solid-free half's ring of slots. */
|
|
8
|
+
const POLE = [0, 0, 1];
|
|
9
|
+
/** Eight slots in a ring round the pole at 36 degrees from it (the ring is about half way out in a picture of the ball seen from its pole), each running along the line to the pole. */
|
|
10
|
+
const COLATITUDE = (36 * Math.PI) / 180;
|
|
11
|
+
const SLOTS = 8;
|
|
12
|
+
/** A slot is 19 mm long on a ball 73.8 mm across (a radius of 36.9 mm): 0.515 radians, half of it 0.2575. Its width is not given; a third of its length is how it is drawn. */
|
|
13
|
+
const HALF_LONG = 19 / 73.8;
|
|
14
|
+
const HALF_WIDTH = HALF_LONG / 3;
|
|
15
|
+
const CENTRES = Array.from({ length: SLOTS }, (_, i) => {
|
|
16
|
+
const a = (i / SLOTS) * 2 * Math.PI + Math.PI / 8;
|
|
17
|
+
return [Math.sin(COLATITUDE) * Math.cos(a), Math.sin(COLATITUDE) * Math.sin(a), Math.cos(COLATITUDE)];
|
|
18
|
+
});
|
|
19
|
+
const DIRS = CENTRES.map((m) => [POLE[0] - m[0] * m[2], POLE[1] - m[1] * m[2], POLE[2] - m[2] * m[2]]);
|
|
20
|
+
export const BALL_PLASTIC_BASEBALL_SLOTTED = /* @__PURE__ */ defineBall({
|
|
21
|
+
id: "ball:plastic-baseball-slotted",
|
|
22
|
+
en: "Plastic baseball, slotted",
|
|
23
|
+
ja: "野球の穴あき練習球",
|
|
24
|
+
size: { extentMm: 73.8, diameterMm: 73.8, rule: "English Wikipedia, the article on the perforated plastic practice ball (accessed 2026-10-21): hollow plastic, wall at most 3.2 mm, eight oblong holes of 19 mm on one half only; size taken from Official Baseball Rules, Rule 3.01 The Ball", note: "The article says only that the ball is about the size of a regulation baseball, so the diameter is a baseball's (the middle of the circumference range). No mass is stated by a source read; none is given. The slots' width is not given and is drawn at a third of their length." },
|
|
25
|
+
spec: {
|
|
26
|
+
view: { yaw: -22, pitch: 22, roll: 0 },
|
|
27
|
+
base: "#f4f4f0",
|
|
28
|
+
mat: { gloss: 0.5, shade: "#3b3e46", grain: { f: 1.4, a: 0.08 } },
|
|
29
|
+
draw: (s) => (s.line ? s.strokes(CENTRES.map((m, i) => slotRing(m, DIRS[i], HALF_WIDTH, HALF_LONG)), "#000", 1, { closed: true }) : ""),
|
|
30
|
+
holes: (s, id, base, shape, minWidth) => holeLayers(s, id, { centres: CENTRES, radius: HALF_WIDTH, long: HALF_LONG, dirs: DIRS }, base, shape, minWidth),
|
|
31
|
+
},
|
|
32
|
+
});
|
|
@@ -45,6 +45,7 @@ export const EMBLEM_DESCRIPTIONS = {
|
|
|
45
45
|
"ball:football-ifaf": { en: "Football (IFAF)", ja: "アメリカンフットボールのボール(IFAF)" },
|
|
46
46
|
"ball:afl": { en: "Australian football", ja: "オーストラリアンフットボールのボール" },
|
|
47
47
|
"ball:gaelic-football": { en: "Gaelic football", ja: "ゲーリックフットボールのボール" },
|
|
48
|
+
"ball:plastic-baseball-slotted": { en: "A hollow white plastic practice baseball with eight oblong slots on one half and the other half solid", ja: "中空の白いプラスチック製の野球練習球。半球の一方に細長い穴が8つ並び、もう一方には穴がない" },
|
|
48
49
|
"ball:squash": { en: "Squash ball, double yellow dot", ja: "スカッシュボール(ダブルイエロードット)" },
|
|
49
50
|
"ball:squash-yellow": { en: "Squash ball, yellow dot", ja: "スカッシュボール(イエロードット)" },
|
|
50
51
|
"ball:squash-green": { en: "Squash ball, green dot", ja: "スカッシュボール(グリーンドット)" },
|
|
@@ -18,7 +18,7 @@ export type CrestShape = (typeof CREST_SHAPES)[number];
|
|
|
18
18
|
export declare const CREST_IDS: readonly ["crest:shield", "crest:roundel", "crest:diamond", "crest:pennant"];
|
|
19
19
|
export type CrestId = (typeof CREST_IDS)[number];
|
|
20
20
|
/** The balls: one for each ball and implement the sports use, in 3D, with the official size it comes from. The balls of one family (the three crickets, the five squash balls) share a module. */
|
|
21
|
-
export declare const BALL_IDS: readonly ["ball:soccer", "ball:soccer-colour", "ball:soccer-26", "ball:soccer-18", "ball:soccer-14", "ball:soccer-12", "ball:soccer-6", "ball:soccer-orange", "ball:soccer-26-orange", "ball:soccer-18-orange", "ball:soccer-14-orange", "ball:soccer-12-orange", "ball:soccer-6-orange", "ball:soccer-yellow", "ball:soccer-26-yellow", "ball:soccer-18-yellow", "ball:soccer-14-yellow", "ball:soccer-12-yellow", "ball:soccer-6-yellow", "ball:futsal", "ball:beach-soccer", "ball:soccer-1870-hand-stitched", "ball:soccer-1900-laced", "ball:soccer-1930-18-panel", "ball:soccer-1950-12-panel", "ball:soccer-1960-32-panel-leather", "ball:soccer-retro-pentagons", "ball:soccer-retro-leaves", "ball:soccer-retro-rosette", "ball:soccer-retro-star", "ball:soccer-retro-pinwheel", "ball:soccer-retro-kites", "ball:soccer-14-panel-double-border", "ball:soccer-8-panel-plain", "ball:soccer-6-panel-bands", "ball:soccer-6-panel-diamonds", "ball:soccer-20-panel-dots", "ball:soccer-training-high-vis", "ball:soccer-stars-blue", "ball:soccer-stars-red", "ball:soccer-stars-night", "ball:soccer-hexagons-cyan", "ball:soccer-hexagons-magenta", "ball:soccer-hexagons-lime", "ball:soccer-flames-fire", "ball:soccer-flames-ice", "ball:soccer-flames-toxic", "ball:soccer-chevrons-red", "ball:soccer-chevrons-green", "ball:soccer-chevrons-blue", "ball:soccer-swirl-blue", "ball:soccer-swirl-red", "ball:soccer-swirl-teal", "ball:soccer-metallic-gold", "ball:soccer-metallic-silver", "ball:soccer-metallic-cobalt", "ball:teqball", "ball:basketball", "ball:basketball-6", "ball:basketball-3x3", "ball:baseball", "ball:softball", "ball:baseball-lemon-peel", "ball:baseball-red-blue", "ball:baseball-black-red", "ball:baseball-vintage-leather", "ball:softball-11-optic", "ball:tennis", "ball:padel", "ball:sliotar", "ball:volleyball", "ball:volleyball-8", "ball:beach-volleyball", "ball:volleyball-colours", "ball:volleyball-brazil", "ball:volleyball-japan", "ball:volleyball-canada", "ball:volleyball-usa", "ball:volleyball-italy", "ball:volleyball-poland", "ball:volleyball-france", "ball:volleyball-serbia", "ball:volleyball-netherlands", "ball:volleyball-germany", "ball:cricket-red", "ball:cricket-white", "ball:cricket-pink", "ball:football", "ball:football-cfl", "ball:football-ifaf", "ball:rugby", "ball:afl", "ball:gaelic-football", "ball:netball", "ball:pickleball-outdoor", "ball:pickleball-indoor", "ball:squash", "ball:squash-yellow", "ball:squash-green", "ball:squash-red", "ball:squash-blue", "ball:racquetball", "ball:lacrosse", "ball:field-hockey", "ball:table-tennis", "ball:handball", "ball:water-polo", "ball:golf", "ball:puck", "ball:curling-stone", "ball:shot", "ball:discus", "ball:hammer", "ball:sepak-takraw", "ball:roundnet", "ball:shuttlecock-feather", "ball:shuttlecock-nylon"];
|
|
21
|
+
export declare const BALL_IDS: readonly ["ball:soccer", "ball:soccer-colour", "ball:soccer-26", "ball:soccer-18", "ball:soccer-14", "ball:soccer-12", "ball:soccer-6", "ball:soccer-orange", "ball:soccer-26-orange", "ball:soccer-18-orange", "ball:soccer-14-orange", "ball:soccer-12-orange", "ball:soccer-6-orange", "ball:soccer-yellow", "ball:soccer-26-yellow", "ball:soccer-18-yellow", "ball:soccer-14-yellow", "ball:soccer-12-yellow", "ball:soccer-6-yellow", "ball:futsal", "ball:beach-soccer", "ball:soccer-1870-hand-stitched", "ball:soccer-1900-laced", "ball:soccer-1930-18-panel", "ball:soccer-1950-12-panel", "ball:soccer-1960-32-panel-leather", "ball:soccer-retro-pentagons", "ball:soccer-retro-leaves", "ball:soccer-retro-rosette", "ball:soccer-retro-star", "ball:soccer-retro-pinwheel", "ball:soccer-retro-kites", "ball:soccer-14-panel-double-border", "ball:soccer-8-panel-plain", "ball:soccer-6-panel-bands", "ball:soccer-6-panel-diamonds", "ball:soccer-20-panel-dots", "ball:soccer-training-high-vis", "ball:soccer-stars-blue", "ball:soccer-stars-red", "ball:soccer-stars-night", "ball:soccer-hexagons-cyan", "ball:soccer-hexagons-magenta", "ball:soccer-hexagons-lime", "ball:soccer-flames-fire", "ball:soccer-flames-ice", "ball:soccer-flames-toxic", "ball:soccer-chevrons-red", "ball:soccer-chevrons-green", "ball:soccer-chevrons-blue", "ball:soccer-swirl-blue", "ball:soccer-swirl-red", "ball:soccer-swirl-teal", "ball:soccer-metallic-gold", "ball:soccer-metallic-silver", "ball:soccer-metallic-cobalt", "ball:teqball", "ball:basketball", "ball:basketball-6", "ball:basketball-3x3", "ball:baseball", "ball:softball", "ball:baseball-lemon-peel", "ball:baseball-red-blue", "ball:baseball-black-red", "ball:baseball-vintage-leather", "ball:softball-11-optic", "ball:tennis", "ball:padel", "ball:sliotar", "ball:volleyball", "ball:volleyball-8", "ball:beach-volleyball", "ball:volleyball-colours", "ball:volleyball-brazil", "ball:volleyball-japan", "ball:volleyball-canada", "ball:volleyball-usa", "ball:volleyball-italy", "ball:volleyball-poland", "ball:volleyball-france", "ball:volleyball-serbia", "ball:volleyball-netherlands", "ball:volleyball-germany", "ball:cricket-red", "ball:cricket-white", "ball:cricket-pink", "ball:football", "ball:football-cfl", "ball:football-ifaf", "ball:rugby", "ball:afl", "ball:gaelic-football", "ball:netball", "ball:pickleball-outdoor", "ball:pickleball-indoor", "ball:plastic-baseball-slotted", "ball:squash", "ball:squash-yellow", "ball:squash-green", "ball:squash-red", "ball:squash-blue", "ball:racquetball", "ball:lacrosse", "ball:field-hockey", "ball:table-tennis", "ball:handball", "ball:water-polo", "ball:golf", "ball:puck", "ball:curling-stone", "ball:shot", "ball:discus", "ball:hammer", "ball:sepak-takraw", "ball:roundnet", "ball:shuttlecock-feather", "ball:shuttlecock-nylon"];
|
|
22
22
|
export type BallId = (typeof BALL_IDS)[number];
|
|
23
23
|
/** The printed pucks: the same puck as `ball:puck` with a print on its top face (a flag, a leaf, stars and stripes, a player's name and number, a made-up signature, a souvenir's ring of words). All drawn here, none a team's or a league's own. */
|
|
24
24
|
export declare const PUCK_IDS: readonly ["puck:canada", "puck:canada-red", "puck:canada-white", "puck:usa", "puck:usa-navy", "puck:player", "puck:signed", "puck:souvenir"];
|
|
@@ -43,7 +43,7 @@ export declare const EMBLEM_GROUPS: {
|
|
|
43
43
|
readonly trophy: readonly ["trophy:cup", "trophy:lidded-cup", "trophy:bowl", "trophy:salver", "trophy:globe", "trophy:hockey-cup", "trophy:basketball", "trophy:baseball", "trophy:football", "trophy:canadian-bowl", "trophy:soccer-ball", "trophy:soccer-globe", "trophy:tennis-plate", "trophy:tennis-cup", "trophy:cricket-urn", "trophy:rugby-cup", "trophy:plaque", "trophy:belt", "trophy:laurel", "trophy:rosette", "trophy:ring", "trophy:banner", "trophy:sumo-cup", "trophy:championship-banner", "trophy:paterson-cup", "trophy:stanley-cup", "trophy:hart-trophy", "trophy:vezina-trophy", "trophy:norris-trophy", "trophy:calder-trophy", "trophy:presidents-trophy", "trophy:art-ross-trophy", "trophy:lady-byng-trophy", "trophy:jennings-trophy", "trophy:selke-trophy", "trophy:king-clancy-trophy", "trophy:masterton-trophy", "trophy:jack-adams-trophy", "trophy:prince-of-wales-trophy", "trophy:campbell-bowl", "trophy:rocket-richard-trophy", "trophy:conn-smythe-trophy", "trophy:ted-lindsay-award", "trophy:lester-patrick-trophy", "trophy:lombardi-trophy", "trophy:larry-obrien-trophy", "trophy:commissioners-trophy", "trophy:grey-cup", "trophy:cy-young-award", "trophy:mlb-mvp-award", "trophy:walter-cup", "trophy:wnba-championship-trophy", "trophy:lamar-hunt-trophy", "trophy:silver-slugger-award", "trophy:world-series-mvp-trophy", "trophy:avco-world-trophy", "trophy:obrien-cup", "trophy:gold-glove-award", "trophy:fifa-world-cup", "trophy:woodlawn-vase", "trophy:dfb-pokal", "trophy:champions-league-trophy", "trophy:webb-ellis-cup", "trophy:fa-cup", "trophy:cricket-world-cup", "trophy:wimbledon-gentlemens-trophy", "trophy:venus-rosewater-dish", "trophy:ballon-dor", "trophy:ashes-urn", "trophy:borg-warner-trophy", "trophy:americas-cup"];
|
|
44
44
|
readonly medal: readonly ["medal:gold", "medal:silver", "medal:bronze", "medal:place-1", "medal:place-2", "medal:place-3"];
|
|
45
45
|
readonly crest: readonly ["crest:shield", "crest:roundel", "crest:diamond", "crest:pennant"];
|
|
46
|
-
readonly ball: readonly ["ball:soccer", "ball:soccer-colour", "ball:soccer-26", "ball:soccer-18", "ball:soccer-14", "ball:soccer-12", "ball:soccer-6", "ball:soccer-orange", "ball:soccer-26-orange", "ball:soccer-18-orange", "ball:soccer-14-orange", "ball:soccer-12-orange", "ball:soccer-6-orange", "ball:soccer-yellow", "ball:soccer-26-yellow", "ball:soccer-18-yellow", "ball:soccer-14-yellow", "ball:soccer-12-yellow", "ball:soccer-6-yellow", "ball:futsal", "ball:beach-soccer", "ball:soccer-1870-hand-stitched", "ball:soccer-1900-laced", "ball:soccer-1930-18-panel", "ball:soccer-1950-12-panel", "ball:soccer-1960-32-panel-leather", "ball:soccer-retro-pentagons", "ball:soccer-retro-leaves", "ball:soccer-retro-rosette", "ball:soccer-retro-star", "ball:soccer-retro-pinwheel", "ball:soccer-retro-kites", "ball:soccer-14-panel-double-border", "ball:soccer-8-panel-plain", "ball:soccer-6-panel-bands", "ball:soccer-6-panel-diamonds", "ball:soccer-20-panel-dots", "ball:soccer-training-high-vis", "ball:soccer-stars-blue", "ball:soccer-stars-red", "ball:soccer-stars-night", "ball:soccer-hexagons-cyan", "ball:soccer-hexagons-magenta", "ball:soccer-hexagons-lime", "ball:soccer-flames-fire", "ball:soccer-flames-ice", "ball:soccer-flames-toxic", "ball:soccer-chevrons-red", "ball:soccer-chevrons-green", "ball:soccer-chevrons-blue", "ball:soccer-swirl-blue", "ball:soccer-swirl-red", "ball:soccer-swirl-teal", "ball:soccer-metallic-gold", "ball:soccer-metallic-silver", "ball:soccer-metallic-cobalt", "ball:teqball", "ball:basketball", "ball:basketball-6", "ball:basketball-3x3", "ball:baseball", "ball:softball", "ball:baseball-lemon-peel", "ball:baseball-red-blue", "ball:baseball-black-red", "ball:baseball-vintage-leather", "ball:softball-11-optic", "ball:tennis", "ball:padel", "ball:sliotar", "ball:volleyball", "ball:volleyball-8", "ball:beach-volleyball", "ball:volleyball-colours", "ball:volleyball-brazil", "ball:volleyball-japan", "ball:volleyball-canada", "ball:volleyball-usa", "ball:volleyball-italy", "ball:volleyball-poland", "ball:volleyball-france", "ball:volleyball-serbia", "ball:volleyball-netherlands", "ball:volleyball-germany", "ball:cricket-red", "ball:cricket-white", "ball:cricket-pink", "ball:football", "ball:football-cfl", "ball:football-ifaf", "ball:rugby", "ball:afl", "ball:gaelic-football", "ball:netball", "ball:pickleball-outdoor", "ball:pickleball-indoor", "ball:squash", "ball:squash-yellow", "ball:squash-green", "ball:squash-red", "ball:squash-blue", "ball:racquetball", "ball:lacrosse", "ball:field-hockey", "ball:table-tennis", "ball:handball", "ball:water-polo", "ball:golf", "ball:puck", "ball:curling-stone", "ball:shot", "ball:discus", "ball:hammer", "ball:sepak-takraw", "ball:roundnet", "ball:shuttlecock-feather", "ball:shuttlecock-nylon"];
|
|
46
|
+
readonly ball: readonly ["ball:soccer", "ball:soccer-colour", "ball:soccer-26", "ball:soccer-18", "ball:soccer-14", "ball:soccer-12", "ball:soccer-6", "ball:soccer-orange", "ball:soccer-26-orange", "ball:soccer-18-orange", "ball:soccer-14-orange", "ball:soccer-12-orange", "ball:soccer-6-orange", "ball:soccer-yellow", "ball:soccer-26-yellow", "ball:soccer-18-yellow", "ball:soccer-14-yellow", "ball:soccer-12-yellow", "ball:soccer-6-yellow", "ball:futsal", "ball:beach-soccer", "ball:soccer-1870-hand-stitched", "ball:soccer-1900-laced", "ball:soccer-1930-18-panel", "ball:soccer-1950-12-panel", "ball:soccer-1960-32-panel-leather", "ball:soccer-retro-pentagons", "ball:soccer-retro-leaves", "ball:soccer-retro-rosette", "ball:soccer-retro-star", "ball:soccer-retro-pinwheel", "ball:soccer-retro-kites", "ball:soccer-14-panel-double-border", "ball:soccer-8-panel-plain", "ball:soccer-6-panel-bands", "ball:soccer-6-panel-diamonds", "ball:soccer-20-panel-dots", "ball:soccer-training-high-vis", "ball:soccer-stars-blue", "ball:soccer-stars-red", "ball:soccer-stars-night", "ball:soccer-hexagons-cyan", "ball:soccer-hexagons-magenta", "ball:soccer-hexagons-lime", "ball:soccer-flames-fire", "ball:soccer-flames-ice", "ball:soccer-flames-toxic", "ball:soccer-chevrons-red", "ball:soccer-chevrons-green", "ball:soccer-chevrons-blue", "ball:soccer-swirl-blue", "ball:soccer-swirl-red", "ball:soccer-swirl-teal", "ball:soccer-metallic-gold", "ball:soccer-metallic-silver", "ball:soccer-metallic-cobalt", "ball:teqball", "ball:basketball", "ball:basketball-6", "ball:basketball-3x3", "ball:baseball", "ball:softball", "ball:baseball-lemon-peel", "ball:baseball-red-blue", "ball:baseball-black-red", "ball:baseball-vintage-leather", "ball:softball-11-optic", "ball:tennis", "ball:padel", "ball:sliotar", "ball:volleyball", "ball:volleyball-8", "ball:beach-volleyball", "ball:volleyball-colours", "ball:volleyball-brazil", "ball:volleyball-japan", "ball:volleyball-canada", "ball:volleyball-usa", "ball:volleyball-italy", "ball:volleyball-poland", "ball:volleyball-france", "ball:volleyball-serbia", "ball:volleyball-netherlands", "ball:volleyball-germany", "ball:cricket-red", "ball:cricket-white", "ball:cricket-pink", "ball:football", "ball:football-cfl", "ball:football-ifaf", "ball:rugby", "ball:afl", "ball:gaelic-football", "ball:netball", "ball:pickleball-outdoor", "ball:pickleball-indoor", "ball:plastic-baseball-slotted", "ball:squash", "ball:squash-yellow", "ball:squash-green", "ball:squash-red", "ball:squash-blue", "ball:racquetball", "ball:lacrosse", "ball:field-hockey", "ball:table-tennis", "ball:handball", "ball:water-polo", "ball:golf", "ball:puck", "ball:curling-stone", "ball:shot", "ball:discus", "ball:hammer", "ball:sepak-takraw", "ball:roundnet", "ball:shuttlecock-feather", "ball:shuttlecock-nylon"];
|
|
47
47
|
readonly puck: readonly ["puck:canada", "puck:canada-red", "puck:canada-white", "puck:usa", "puck:usa-navy", "puck:player", "puck:signed", "puck:souvenir"];
|
|
48
48
|
readonly gear: readonly ["gear:hockey-stick", "gear:goalie-stick", "gear:hockey-skate", "gear:goalie-mask", "gear:goal-net", "gear:field-hockey-stick", "gear:lacrosse-stick", "gear:cricket-bat", "gear:wicket", "gear:table-tennis-paddle", "gear:badminton-racket", "gear:tennis-racket", "gear:squash-racket", "gear:racquetball-racket", "gear:padel-racket", "gear:pickleball-paddle", "gear:roundnet-set", "gear:takraw-net", "gear:netball-post", "gear:teqball-table", "gear:volleyball-net", "gear:basketball-hoop", "gear:baseball-bat", "gear:baseball-glove", "gear:football-helmet", "gear:goalposts", "gear:hurley", "gear:curling-broom", "gear:figure-skate", "gear:speed-skate", "gear:diving-board", "gear:swim-goggles", "gear:starting-blocks", "gear:relay-baton", "gear:javelin", "gear:hurdles", "gear:gunbai", "gear:mawashi", "gear:shinai", "gear:kendo-men", "gear:judogi", "gear:judogi-blue", "gear:judogi-folded", "gear:judogi-blue-folded", "gear:judogi-back", "gear:judogi-blue-back", "gear:obi", "gear:obi-white", "gear:obi-yellow", "gear:obi-orange", "gear:obi-green", "gear:obi-blue", "gear:obi-brown", "gear:obi-kohaku", "gear:obi-red", "gear:obi-women", "gear:obi-white-yellow", "gear:obi-yellow-orange", "gear:obi-orange-green", "gear:obi-green-blue", "gear:obi-blue-brown", "gear:obi-step-1", "gear:obi-step-2", "gear:obi-step-3", "gear:obi-step-4", "gear:obi-step-5", "gear:obi-step-6", "gear:yumi", "gear:ya", "gear:karate-gi"];
|
|
49
49
|
readonly sport: readonly ("sport:sumo" | "sport:kendo" | "sport:judo" | "sport:kyudo" | "sport:karate" | "sport:nfl" | "sport:cfl" | "sport:ifaf" | "sport:nhl" | "sport:nba" | "sport:mlb" | "sport:soccer" | "sport:curling" | "sport:tennis" | "sport:volleyball" | "sport:badminton" | "sport:pickleball" | "sport:tabletennis" | "sport:padel" | "sport:squash" | "sport:racquetball" | "sport:sepaktakraw" | "sport:teqball" | "sport:roundnet" | "sport:netball" | "sport:swimming" | "sport:waterpolo" | "sport:diving" | "sport:artisticswimming" | "sport:lacrosse" | "sport:rugby" | "sport:afl" | "sport:gaelic" | "sport:cricket" | "sport:fieldhockey" | "sport:handball" | "sport:athletics" | "sport:skating" | "sport:mma" | "sport:boxing" | "sport:wrestling" | "sport:prowrestling")[];
|
|
@@ -75,7 +75,7 @@ export const BALL_IDS = [
|
|
|
75
75
|
"ball:soccer", "ball:soccer-colour", "ball:soccer-26", "ball:soccer-18", "ball:soccer-14", "ball:soccer-12", "ball:soccer-6", "ball:soccer-orange", "ball:soccer-26-orange", "ball:soccer-18-orange", "ball:soccer-14-orange", "ball:soccer-12-orange", "ball:soccer-6-orange", "ball:soccer-yellow", "ball:soccer-26-yellow", "ball:soccer-18-yellow", "ball:soccer-14-yellow", "ball:soccer-12-yellow", "ball:soccer-6-yellow", "ball:futsal", "ball:beach-soccer",
|
|
76
76
|
"ball:soccer-1870-hand-stitched", "ball:soccer-1900-laced", "ball:soccer-1930-18-panel", "ball:soccer-1950-12-panel", "ball:soccer-1960-32-panel-leather", "ball:soccer-retro-pentagons", "ball:soccer-retro-leaves", "ball:soccer-retro-rosette", "ball:soccer-retro-star", "ball:soccer-retro-pinwheel", "ball:soccer-retro-kites", "ball:soccer-14-panel-double-border", "ball:soccer-8-panel-plain", "ball:soccer-6-panel-bands", "ball:soccer-6-panel-diamonds", "ball:soccer-20-panel-dots", "ball:soccer-training-high-vis", "ball:soccer-stars-blue", "ball:soccer-stars-red", "ball:soccer-stars-night", "ball:soccer-hexagons-cyan", "ball:soccer-hexagons-magenta", "ball:soccer-hexagons-lime", "ball:soccer-flames-fire", "ball:soccer-flames-ice", "ball:soccer-flames-toxic", "ball:soccer-chevrons-red", "ball:soccer-chevrons-green", "ball:soccer-chevrons-blue", "ball:soccer-swirl-blue", "ball:soccer-swirl-red", "ball:soccer-swirl-teal", "ball:soccer-metallic-gold", "ball:soccer-metallic-silver", "ball:soccer-metallic-cobalt", "ball:teqball", "ball:basketball", "ball:basketball-6", "ball:basketball-3x3", "ball:baseball", "ball:softball", "ball:baseball-lemon-peel", "ball:baseball-red-blue", "ball:baseball-black-red", "ball:baseball-vintage-leather", "ball:softball-11-optic", "ball:tennis", "ball:padel",
|
|
77
77
|
"ball:sliotar", "ball:volleyball", "ball:volleyball-8", "ball:beach-volleyball", "ball:volleyball-colours", "ball:volleyball-brazil", "ball:volleyball-japan", "ball:volleyball-canada", "ball:volleyball-usa", "ball:volleyball-italy", "ball:volleyball-poland", "ball:volleyball-france", "ball:volleyball-serbia", "ball:volleyball-netherlands", "ball:volleyball-germany", "ball:cricket-red", "ball:cricket-white", "ball:cricket-pink", "ball:football", "ball:football-cfl",
|
|
78
|
-
"ball:football-ifaf", "ball:rugby", "ball:afl", "ball:gaelic-football", "ball:netball", "ball:pickleball-outdoor", "ball:pickleball-indoor", "ball:squash", "ball:squash-yellow",
|
|
78
|
+
"ball:football-ifaf", "ball:rugby", "ball:afl", "ball:gaelic-football", "ball:netball", "ball:pickleball-outdoor", "ball:pickleball-indoor", "ball:plastic-baseball-slotted", "ball:squash", "ball:squash-yellow",
|
|
79
79
|
"ball:squash-green", "ball:squash-red", "ball:squash-blue", "ball:racquetball", "ball:lacrosse", "ball:field-hockey", "ball:table-tennis", "ball:handball", "ball:water-polo", "ball:golf",
|
|
80
80
|
"ball:puck", "ball:curling-stone", "ball:shot", "ball:discus", "ball:hammer", "ball:sepak-takraw", "ball:roundnet", "ball:shuttlecock-feather", "ball:shuttlecock-nylon"
|
|
81
81
|
];
|
package/dist/index.d.ts
CHANGED
|
@@ -152,6 +152,7 @@ export { BALL_HAMMER } from "./emblems/ball/ball.hammer.ts";
|
|
|
152
152
|
export { BALL_HANDBALL } from "./emblems/ball/ball.handball.ts";
|
|
153
153
|
export { BALL_PADEL } from "./emblems/ball/ball.padel.ts";
|
|
154
154
|
export { BALL_PICKLEBALL_OUTDOOR, BALL_PICKLEBALL_INDOOR } from "./emblems/ball/ball.pickleball.ts";
|
|
155
|
+
export { BALL_PLASTIC_BASEBALL_SLOTTED } from "./emblems/ball/ball.plastic.ts";
|
|
155
156
|
export { BALL_PUCK } from "./emblems/ball/ball.puck.ts";
|
|
156
157
|
export { PUCK_CANADA, PUCK_CANADA_RED, PUCK_CANADA_WHITE, PUCK_USA, PUCK_USA_NAVY, PUCK_PLAYER, PUCK_SIGNED, PUCK_SOUVENIR } from "./emblems/ball/ball.puck.print.ts";
|
|
157
158
|
export { BALL_ROUNDNET } from "./emblems/ball/ball.roundnet.ts";
|
package/dist/index.js
CHANGED
|
@@ -152,6 +152,7 @@ export { BALL_HAMMER } from "./emblems/ball/ball.hammer.js";
|
|
|
152
152
|
export { BALL_HANDBALL } from "./emblems/ball/ball.handball.js";
|
|
153
153
|
export { BALL_PADEL } from "./emblems/ball/ball.padel.js";
|
|
154
154
|
export { BALL_PICKLEBALL_OUTDOOR, BALL_PICKLEBALL_INDOOR } from "./emblems/ball/ball.pickleball.js";
|
|
155
|
+
export { BALL_PLASTIC_BASEBALL_SLOTTED } from "./emblems/ball/ball.plastic.js";
|
|
155
156
|
export { BALL_PUCK } from "./emblems/ball/ball.puck.js";
|
|
156
157
|
export { PUCK_CANADA, PUCK_CANADA_RED, PUCK_CANADA_WHITE, PUCK_USA, PUCK_USA_NAVY, PUCK_PLAYER, PUCK_SIGNED, PUCK_SOUVENIR } from "./emblems/ball/ball.puck.print.js";
|
|
157
158
|
export { BALL_ROUNDNET } from "./emblems/ball/ball.roundnet.js";
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.16.0";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "0.
|
|
1
|
+
export const VERSION = "0.16.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@johnmorrisdotca/dougu-sports",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Dougu Sports 道具, sports emblems as SVG strings: trophies, medals, crests, sport icons, and the ball and gear of every sport, in metal, line or flat colour, with optional 3D turning. Light and dark, accessible, tree-shakeable. Zero dependencies.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sports",
|