@johnmorrisdotca/dougu-sports 0.9.0 → 0.10.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 +9 -0
- package/NOTICE.md +14 -0
- package/README.md +6 -3
- package/dist/brands/brand.ball.d.ts +29 -0
- package/dist/brands/brand.ball.js +23 -0
- package/dist/brands/brand.data.d.ts +47 -0
- package/dist/brands/brand.data.js +308 -0
- package/dist/brands/brand.letters.d.ts +31 -0
- package/dist/brands/brand.letters.js +88 -0
- package/dist/brands/brand.render.d.ts +47 -0
- package/dist/brands/brand.render.js +106 -0
- package/dist/brands-entry.d.ts +8 -0
- package/dist/brands-entry.js +5 -0
- package/dist/emblems/award/ribbon.d.ts +2 -0
- package/dist/emblems/award/ribbon.js +17 -0
- package/dist/emblems/emblem.equipment.js +3 -3
- package/dist/emblems/emblem.ids.d.ts +4 -4
- package/dist/emblems/emblem.ids.js +2 -2
- package/dist/emblems/emblem.registry.js +2 -0
- package/dist/emblems/gear/gear.index.js +2 -1
- package/dist/emblems/gear/gear.nets.d.ts +3 -0
- package/dist/emblems/gear/gear.nets.js +103 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,15 @@ All notable changes to this project are written here. The format follows
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.10.0] - 2026-10-19
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- **`award:ribbon`**, a ribbon on its own (a band with two swallow-tailed ends folded behind it), drawn for this package, in metal, colour and line like the other awards. 273 emblems.
|
|
14
|
+
- **Nets and posts for three sports**, from their rulebooks' sizes (sources in NOTICE.md): `gear:takraw-net` (ISTAF Law of the Game, Regu: posts 1.55 m, net 0.7 m deep, 1.52 m at the centre), `gear:netball-post` (World Netball Rules of Netball 2024: a 3.05 m pole, a ring of 380 mm inside diameter) and `gear:teqball-table` (FITEQ Official Rules and Regulations of Teqball 2025: 3,000 mm long, surface 760 mm and 565 mm high, 900 mm with the net). They are the equipment of `sepaktakraw`, `netball` and `teqball` in `sportEquipment`. What is not to scale (a net drawn shorter, a rod drawn wider, the table's legs) is said in each file.
|
|
15
|
+
- **The demo's podium shows Hata's round flags** for Japan, France and Italy (`demo/flags-data.ts`, made by `pnpm flags`; Hata 1.5.0 is a development dependency of the demo only), in place of three flags drawn by hand. The package is unchanged.
|
|
16
|
+
- **Made-up maker and team logos (experimental, designs will change)**, in a new entry point `@johnmorrisdotca/dougu-sports/brands`: twelve fictional makers of balls and gear (`arvane`, `tarsin`, `ravelle`, `kovreth`, `dunmar`, `ostrel`, `vexlin`, `quillan`, `tenzar`, `marenko`, `halvane`, `solvik`) and ten fictional teams (`saltmere`, `greywick`, `brightwater`, `cinderfell`, `valmere`, `larkmoor`, `ironport`, `pinecrest`, `redfern`, `tarn`), as SVG. A mark stands alone and is what `makerLogo` draws by default; the name is optional (`layout: "wordmark" | "horizontal" | "stacked"`). Full colour or one colour, light or dark, with a note on the nearest real brand and how each differs. `makerLogoGroup` and `teamLogoGroup` return a `<g>` to place in another drawing; `makerBall` and `renderMakerBall` print a maker's mark on a baseball, a softball or a classic soccer ball. The set is data (`MAKERS`, `TEAMS`). The demo has a contact sheet (`brands.html`). See `docs/brands.md`.
|
|
17
|
+
|
|
9
18
|
## [0.9.0] - 2026-10-15
|
|
10
19
|
|
|
11
20
|
### Added
|
package/NOTICE.md
CHANGED
|
@@ -4,12 +4,16 @@ The code of this package is under the MIT licence (see [LICENSE](LICENSE) and [L
|
|
|
4
4
|
|
|
5
5
|
No emblem carries the name, mark or logo of a league, a team, a federation or an event: the trophies, crests, balls and gear are descriptive and generic. That includes the Japanese items (`trophy:sumo-cup`, `trophy:championship-banner` and the `gear:*` of sumo, kendo, judo, kyudo and karate): they are original drawings of what such an object looks like, with generic ids, and carry no trophy's name, no federation's mark and no lettering unless the caller gives some.
|
|
6
6
|
|
|
7
|
+
The made-up maker marks and team logos (`@johnmorrisdotca/dougu-sports/brands`) are fictional: their names, marks, lettering and colours are invented for this package, each is noted with the real brand it is nearest to and how it differs, and none is a real company's or club's. They are under the same MIT licence. Nothing of SPX, SPXN, SPXIS or SportsInteractive is in the package.
|
|
8
|
+
|
|
7
9
|
## How the art is made
|
|
8
10
|
|
|
9
11
|
- The trophies, medals, crests, awards and sport pictograms are drawn in SVG by hand in a simplified, generic form. No real trophy, medal, logo, mark or engraving was copied or traced, and no photograph was traced (photographs were looked at, never copied).
|
|
10
12
|
- The balls (`src/emblems/ball/`) are drawn by this package's own code: a rotation, a projection and our own geometry (a seam curve, the truncated icosahedron, an octahedron and an icosahedron, a layout of curved panels, a fitted basketball channel). The vintage, era-style and patterned balls ([docs/vintage-balls.md](docs/vintage-balls.md)) are our own graphics laid on those constructions (shapes placed on the sphere, rows of stitches, a lace, scuffs): the shop-wall patterns and the era styles were suggested by photographs the package's author supplied, which were looked at and not copied or traced, and no real ball's pattern, mark or name is used. The volleyballs take only three colours from a country's flag, and draw no flag.
|
|
11
13
|
- The printed pucks (`puck:*`, `src/emblems/ball/ball.puck.print.ts`) are our own drawings: the maple leaf, the flags of the Canadian and United States patterns and the stars are drawn from simple geometry, the lettering is a stroke alphabet adapted from the block letters of the author's own senshu-jerseys (same author, same MIT licence, no font file), and the signature is made by a seeded pen, so it is no real person's. Photographs of souvenir pucks were looked at for what such a puck shows (a flag, a name, a number, a signature, a ring of words) and nothing was copied or traced. No team's or league's logo or wordmark, no maker's mark and no real player's name is used.
|
|
14
|
+
- The made-up logos (`src/brands/`) are our own geometry: polygons, arcs and spirals worked out for this package and tuned by eye, with wordmarks set in our own stroke alphabet (`brand.letters.ts`, no font file). No real logo was traced, and no real mark was used as a base; the notes in `docs/brands.md` say what each was held against.
|
|
12
15
|
- The gear (`src/emblems/gear/`) is drawn by us from a list of parts (a path, a colour, how it reads as a line); the bow, the arrow and the other tapering shapes are made by a small function of ours (`swell`), and the rest are paths written for this package.
|
|
16
|
+
- The demo's podium shows the round flags of Japan, France and Italy from [Hata](https://github.com/johnmorrisdotca/hata) 1.5.0 (`demo/flags-data.ts`, made by `scripts/make-flags.mjs`; a development dependency of the demo, never of the package). Hata's manifest lists each of the three as public domain, so no credit is required.
|
|
13
17
|
- The backgrounds behind the README pictures and the demo's preview (`scripts/family-backgrounds.ts`, version 1.0.0) are the family's shared module, copied byte for byte from taisen-brackets: twenty-five backgrounds drawn in code from gradients, patterns and paths, all by this package's author, none traced from a picture, a poster, a logo, a trophy or a photograph (MIT). It is tooling: the package ships none of it, and no emblem is drawn on a background.
|
|
14
18
|
- The Japanese words for the Japanese items are the ones the sports' governing bodies use in their own rules and equipment lists (kendo, judo, kyudo and karate federations and the sumo association); the bodies' names and marks are not used in any id, title or drawing.
|
|
15
19
|
|
|
@@ -67,6 +71,16 @@ Each ball's `size.rule` names the rule; the table gives the document and where i
|
|
|
67
71
|
|
|
68
72
|
Facts only: a dimension or a mass is a fact, not a work. The NHL's puck rule was not read (the NHL's site was not fetched); the puck's size is the IIHF's.
|
|
69
73
|
|
|
74
|
+
### The rulebooks the nets and posts are read from
|
|
75
|
+
|
|
76
|
+
A piece of gear claims no size of its own, but these three are drawn from the sizes a rulebook gives, where the drawing allows. Each drawing's file says what is not to scale. A size the rulebook does not give is not drawn from any source: the legs of the teqball table and the thickness of its surface are drawn by eye.
|
|
77
|
+
|
|
78
|
+
| Gear | Rulebook and rule | Read at |
|
|
79
|
+
| --- | --- | --- |
|
|
80
|
+
| `gear:takraw-net` | ISTAF Law of the Game, Sepaktakraw Regu, 2024 text (amendments approved 15 July 2023 and 8 December 2023; dated 1 January 2024): 2.1 posts 1.55 m men, 1.45 m women, radius not more than 0.04 m; 3.2 net 0.7 m wide, not shorter than 6.1 m; 3.5 net 1.52 m at the centre and 1.55 m at the posts (men) | https://img1.wsimg.com/blobby/go/b28abe2b-c8e0-4c25-b6ac-d2655417c6c3/Law%20of%20the%20Game%202024%20-%20Regu%20-.pdf |
|
|
81
|
+
| `gear:netball-post` | World Netball Rules of Netball, 2024 edition, Rule 1 Technical specifications, 1.13 (placing) and 1.14 (a pole 65-100 mm across and 3.05 m high, padding up to 50 mm; a ring of 15 mm rod with an internal diameter of 380 mm; a 150 mm bar; a net 380-457 mm long) | https://netballhamilton.org.nz/media/1997/world-netball-rules-book-2024.pdf |
|
|
82
|
+
| `gear:teqball-table` | FITEQ Official Rules and Regulations of Teqball, 2025 (effective 5 February 2025), 1.1.1-1.1.5 the table (3,000 mm long, 1,700 mm wide with the net, 900 mm high with the net, surface 760 mm at its highest and 565 mm at its lowest, 1,490 mm from the net to the lowest point) and 1.2.1-1.2.3 the net (1,700 mm wide, 20 mm thick, 140 mm above the surface) | https://cdn.buttercms.com/YBHXKq7GTv2wXkTVQbNC |
|
|
83
|
+
|
|
70
84
|
## The demo and the docs
|
|
71
85
|
|
|
72
86
|
| What | Made from | Terms |
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ The ball and the gear of every sport, trophies, medals, crests and the icon of e
|
|
|
52
52
|
</tr>
|
|
53
53
|
</table>
|
|
54
54
|
|
|
55
|
-
> **Status: preview.**
|
|
55
|
+
> **Status: preview.** 273 emblems: 24 trophies, 6 awards, 6 medals, 4 crests, a pictogram for each of the 38 sports, 116 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.
|
|
56
56
|
|
|
57
57
|
## In 30 seconds
|
|
58
58
|
|
|
@@ -92,7 +92,8 @@ Put the string in a page (`element.innerHTML = svg`), write it to a file, or sen
|
|
|
92
92
|
- **Short names and helpers**: `"cup"` is `"trophy:cup"`, `"trophy:cup/line"` is the line style, and `crest`, `medal`, `sportIcon` and `pennant` draw a team's crest, a medal, a sport's icon and a championship pennant.
|
|
93
93
|
- **Typed ids**: `EmblemId` is a union of `award:*`, `trophy:*`, `medal:*`, `crest:*`, `ball:*`, `gear:*`, `sport:*` and `pennant:*` ids.
|
|
94
94
|
- **Japanese sports and budō** (道具 is the name): a sumo cup, a championship banner, and the war fan, belt, bamboo sword, kendo helmet, judo and karate suits, the white and blue judo suit flat, folded and seen from behind with its back number ([docs/judogi-back.md](./docs/judogi-back.md)), the belts of every grade and six pictures of how the belt is tied ([docs/obi-steps.md](./docs/obi-steps.md)), long bow and arrow, with Japanese names that are the governing bodies' words; see [docs/japanese-sports.md](./docs/japanese-sports.md).
|
|
95
|
-
- **
|
|
95
|
+
- **Made-up logos, experimental** (`@johnmorrisdotca/dougu-sports/brands`; a draft, the designs will change and it is not a supported feature yet): twelve fictional makers of balls and gear and ten fictional teams, each a bold geometric mark that stands alone (the name is optional), in colour or one colour, light and dark, with a note on the real brand it is nearest to and how it differs; a maker's mark prints on a baseball, a softball or a classic soccer ball, and a group places any logo inside your own drawing; see [docs/brands.md](./docs/brands.md).
|
|
96
|
+
- **Generic by design**: no emblem carries a league's, a team's or a federation's name or mark, and the made-up logos are nobody's.
|
|
96
97
|
- **Accessible**: every drawing is `role="img"` with a `<title>`; see [Accessibility](#accessibility).
|
|
97
98
|
- **Deterministic**: the same id and options give the same string; a gradient's id comes from its colour.
|
|
98
99
|
- **No dependencies**, ESM with types.
|
|
@@ -138,6 +139,7 @@ The alias is a name in your `package.json` only: the same package, the same code
|
|
|
138
139
|
| --- | --- |
|
|
139
140
|
| `@johnmorrisdotca/dougu-sports` | The full registry: every emblem by id, the functions, and each emblem as a constant |
|
|
140
141
|
| `@johnmorrisdotca/dougu-sports/emblems` | `renderEmblem`, the ids and the types, with no single drawing imported by name |
|
|
142
|
+
| `@johnmorrisdotca/dougu-sports/brands` | Experimental, designs will change: twelve made-up maker marks and ten made-up team logos as SVG (`makerLogo`, `teamLogo`, `makerBall`, `renderMakerBall`, the groups to place in a drawing and the data); see [docs/brands.md](./docs/brands.md) |
|
|
141
143
|
| `@johnmorrisdotca/dougu-sports/turn` | `emblemFrame`, `ballFrame` and `bindTurn`; `bindTurn` with an emblem object takes nothing else with it |
|
|
142
144
|
| `@johnmorrisdotca/dougu-sports/<group>/<name>` | One emblem, alone: `trophy/hockey-cup`, `medal/gold`, `crest/shield`, `sport/nhl`, `award/crown`, `ball/soccer`, `pennant/championship`, `gear/<name>` |
|
|
143
145
|
|
|
@@ -509,6 +511,7 @@ The metals are `METALS` (gold `#d9a620`, silver `#aeb6c0`, bronze `#b8733a`); ea
|
|
|
509
511
|
- A trophy in the metal style is about 3 to 4.5 kB of markup, a medal or a crest about 1 to 2 kB, a line drawing about 1 to 2.5 kB; a ball in 3D is 5 to 13 kB, and a piece of gear is 1 to 4 kB, drawn in layers.
|
|
510
512
|
- The size is a number of pixels up to 4096; the drawing is a vector at any size.
|
|
511
513
|
- No emblem carries a real league's, team's or federation's mark.
|
|
514
|
+
- No jerseys: a jersey, a cap or a kit is drawn by [Senshu Jerseys](https://github.com/johnmorrisdotca/senshu-jerseys), its own package (a `jersey()` made here in 0.2.0's draft was taken out and moved there). The pennant, the ring, the banner and the made-up maker and team logos stay here.
|
|
512
515
|
|
|
513
516
|
## Accessibility
|
|
514
517
|
|
|
@@ -634,7 +637,7 @@ Bug reports and ideas go in the [issues](https://github.com/johnmorrisdotca/doug
|
|
|
634
637
|
|
|
635
638
|
## Changes
|
|
636
639
|
|
|
637
|
-
See [CHANGELOG.md](./CHANGELOG.md). 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.
|
|
640
|
+
See [CHANGELOG.md](./CHANGELOG.md). 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.
|
|
638
641
|
|
|
639
642
|
## Credits
|
|
640
643
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type EmblemRef } from "../emblems/emblem.api.ts";
|
|
2
|
+
import type { EmblemOptions } from "../emblems/emblem.core.ts";
|
|
3
|
+
import type { MakerId } from "./brand.data.ts";
|
|
4
|
+
import { type MakerLogoOptions } from "./brand.render.ts";
|
|
5
|
+
/** How a maker's logo sits on a ball. */
|
|
6
|
+
export interface MakerBallOptions extends Omit<MakerLogoOptions, "size" | "title"> {
|
|
7
|
+
/** How wide the logo is, in degrees of the ball (the mark alone 50 by default, a layout with a wordmark 74). */
|
|
8
|
+
width?: number;
|
|
9
|
+
/** A turn of the logo on the ball, in degrees. */
|
|
10
|
+
turn?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* The ball options that print a maker's logo on it: `{ decal: { svg, size, turn } }`, to spread into the options of `renderEmblem`, `emblemFrame` or `bindTurn`. The logo is wrapped onto the sphere, so it curves with the ball and turns with it.
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { makerBall } from "@johnmorrisdotca/dougu-sports/brands";
|
|
17
|
+
* console.log(makerBall("arvane").decal.svg.includes("<path"));
|
|
18
|
+
* // true
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export declare function makerBall(id: MakerId, o?: MakerBallOptions): {
|
|
22
|
+
decal: {
|
|
23
|
+
svg: string;
|
|
24
|
+
size: number;
|
|
25
|
+
turn: number;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
/** A ball with a maker's logo printed on it: `renderMakerBall("ball:baseball", "arvane", { size: 320 })`. Any other options of the ball (`paint`, `stamp`, `spots`...) go in `ball`. */
|
|
29
|
+
export declare function renderMakerBall(ball: EmblemRef, id: MakerId, o?: MakerBallOptions, ballOptions?: EmblemOptions): string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Puts a maker's mark on a ball: the options that print it (`decal`), and the ball drawn with them. The balls that take a printed logo are the baseball, the softball and the classic soccer balls (see docs/custom-balls.md);
|
|
2
|
+
// any other ball ignores the print and is drawn plain.
|
|
3
|
+
import { renderEmblem } from "../emblems/emblem.api.js";
|
|
4
|
+
import { makerLogo } from "./brand.render.js";
|
|
5
|
+
/**
|
|
6
|
+
* The ball options that print a maker's logo on it: `{ decal: { svg, size, turn } }`, to spread into the options of `renderEmblem`, `emblemFrame` or `bindTurn`. The logo is wrapped onto the sphere, so it curves with the ball and turns with it.
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { makerBall } from "@johnmorrisdotca/dougu-sports/brands";
|
|
10
|
+
* console.log(makerBall("arvane").decal.svg.includes("<path"));
|
|
11
|
+
* // true
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function makerBall(id, o) {
|
|
15
|
+
const layout = o?.layout ?? "mark";
|
|
16
|
+
const size = typeof o?.width === "number" && Number.isFinite(o.width) ? Math.min(Math.max(o.width, 8), 120) : layout === "mark" ? 50 : 74;
|
|
17
|
+
const turn = typeof o?.turn === "number" && Number.isFinite(o.turn) ? o.turn : 0;
|
|
18
|
+
return { decal: { svg: makerLogo(id, { ...o, title: false, size: 200 }), size, turn } };
|
|
19
|
+
}
|
|
20
|
+
/** A ball with a maker's logo printed on it: `renderMakerBall("ball:baseball", "arvane", { size: 320 })`. Any other options of the ball (`paint`, `stamp`, `spots`...) go in `ball`. */
|
|
21
|
+
export function renderMakerBall(ball, id, o, ballOptions) {
|
|
22
|
+
return renderEmblem(ball, { ...ballOptions, ...makerBall(id, o) });
|
|
23
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { LetterStyle } from "./brand.letters.ts";
|
|
2
|
+
export type PartRole = "a" | "b" | "c";
|
|
3
|
+
/** One flat shape of a mark: an SVG path (drawn with the even-odd rule, so a hole is a hole) and the colour it takes. */
|
|
4
|
+
export interface LogoPart {
|
|
5
|
+
d: string;
|
|
6
|
+
role: PartRole;
|
|
7
|
+
}
|
|
8
|
+
/** The colours of a maker on a light page or a dark one: the two of its mark and the ink of its wordmark. */
|
|
9
|
+
export interface MakerPalette {
|
|
10
|
+
a: string;
|
|
11
|
+
b: string;
|
|
12
|
+
ink: string;
|
|
13
|
+
}
|
|
14
|
+
/** The three colours of a team logo on a light page or a dark one. */
|
|
15
|
+
export interface TeamPalette {
|
|
16
|
+
a: string;
|
|
17
|
+
b: string;
|
|
18
|
+
c: string;
|
|
19
|
+
}
|
|
20
|
+
/** A fictional maker of balls and sports gear: a mark, a name to set as a wordmark, two palettes and the note of how it differs from the nearest real brand. */
|
|
21
|
+
export interface MakerData {
|
|
22
|
+
id: MakerId;
|
|
23
|
+
name: string;
|
|
24
|
+
genre: string;
|
|
25
|
+
note: string;
|
|
26
|
+
parts: readonly LogoPart[];
|
|
27
|
+
light: MakerPalette;
|
|
28
|
+
dark: MakerPalette;
|
|
29
|
+
lettering: LetterStyle;
|
|
30
|
+
}
|
|
31
|
+
/** A fictional team: a city and a nickname, a logo, two palettes and a note. */
|
|
32
|
+
export interface TeamData {
|
|
33
|
+
id: TeamId;
|
|
34
|
+
city: string;
|
|
35
|
+
nickname: string;
|
|
36
|
+
genre: string;
|
|
37
|
+
note: string;
|
|
38
|
+
parts: readonly LogoPart[];
|
|
39
|
+
light: TeamPalette;
|
|
40
|
+
dark: TeamPalette;
|
|
41
|
+
}
|
|
42
|
+
export declare const MAKER_IDS: readonly ["arvane", "tarsin", "ravelle", "kovreth", "dunmar", "ostrel", "vexlin", "quillan", "tenzar", "marenko", "halvane", "solvik"];
|
|
43
|
+
export type MakerId = (typeof MAKER_IDS)[number];
|
|
44
|
+
export declare const TEAM_IDS: readonly ["saltmere", "greywick", "brightwater", "cinderfell", "valmere", "larkmoor", "ironport", "pinecrest", "redfern", "tarn"];
|
|
45
|
+
export type TeamId = (typeof TEAM_IDS)[number];
|
|
46
|
+
export declare const MAKERS: Readonly<Record<MakerId, MakerData>>;
|
|
47
|
+
export declare const TEAMS: Readonly<Record<TeamId, TeamData>>;
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
// The set: twelve fictional maker marks and ten fictional team logos, as data. Every mark is drawn for this package on a 100 by 100 box in a few flat parts, each part one path and one role (`a` the main colour, `b` the second, `c` a third
|
|
2
|
+
// for a team); the parts never overlap, so the mark is the same drawn in one colour. Nothing here is a real company's or club's mark, name or lettering: each note says what the nearest real one is and how this differs.
|
|
3
|
+
export const MAKER_IDS = ["arvane", "tarsin", "ravelle", "kovreth", "dunmar", "ostrel", "vexlin", "quillan", "tenzar", "marenko", "halvane", "solvik"];
|
|
4
|
+
export const TEAM_IDS = ["saltmere", "greywick", "brightwater", "cinderfell", "valmere", "larkmoor", "ironport", "pinecrest", "redfern", "tarn"];
|
|
5
|
+
const part = (role, d) => ({ role, d });
|
|
6
|
+
export const MAKERS = Object.freeze({
|
|
7
|
+
arvane: {
|
|
8
|
+
id: "arvane",
|
|
9
|
+
name: "Arvane",
|
|
10
|
+
genre: "stripes",
|
|
11
|
+
note: "Nearest: the Adidas performance mark, three slanted stripes that make a triangle. Arvane is one upright triangle cut into three level bands with a notch in the base, in green and amber; there is no slanted stripe at all.",
|
|
12
|
+
parts: [
|
|
13
|
+
part("a", "M49.3 11.3Q50 10 50.7 11.3L62.8 32.7Q63.5 34 62 34L38 34Q36.5 34 37.2 32.7Z"),
|
|
14
|
+
part("b", "M32.3 41.3Q33.1 40 34.6 40L65.4 40Q66.9 40 67.7 41.3L78.6 60.7Q79.3 62 77.8 62L22.2 62Q20.7 62 21.4 60.7Z"),
|
|
15
|
+
part("a", "M16.6 69.3Q17.3 68 18.8 68L81.2 68Q82.7 68 83.4 69.3L93.3 86.7Q94 88 92.5 88L61.5 88Q60 88 58.9 86.9L51.1 79.1Q50 78 48.9 79.1L41.1 86.9Q40 88 38.5 88L7.5 88Q6 88 6.7 86.7Z"),
|
|
16
|
+
],
|
|
17
|
+
light: { a: "#0f5a46", b: "#f2a33a", ink: "#0f2f27" },
|
|
18
|
+
dark: { a: "#3fc59a", b: "#f7b955", ink: "#eaf6f1" },
|
|
19
|
+
lettering: { weight: 11, corner: "sharp", radius: 0, width: 0.8, gap: 14, slant: 0, cap: "butt" },
|
|
20
|
+
},
|
|
21
|
+
tarsin: {
|
|
22
|
+
id: "tarsin",
|
|
23
|
+
name: "Tarsin",
|
|
24
|
+
genre: "animal",
|
|
25
|
+
note: "Nearest: Orca, the triathlon and swim maker whose mark is a whole orca. Tarsin shows only the symmetrical tail fluke over two waterline bars, in indigo and cyan, and no body.",
|
|
26
|
+
parts: [
|
|
27
|
+
part("a", "M50 40C42 33 26 34 6 22C10 46 28 62 46 62L45 80L55 80L54 62C72 62 90 46 94 22C74 34 58 33 50 40Z"),
|
|
28
|
+
part("b", "M6 89Q6 86 9 86L39 86Q42 86 42 89L42 89Q42 92 39 92L9 92Q6 92 6 89Z"),
|
|
29
|
+
part("b", "M58 89Q58 86 61 86L91 86Q94 86 94 89L94 89Q94 92 91 92L61 92Q58 92 58 89Z"),
|
|
30
|
+
],
|
|
31
|
+
light: { a: "#1d2d78", b: "#3fb8cf", ink: "#141d4f" },
|
|
32
|
+
dark: { a: "#8fa2ff", b: "#5fd0e3", ink: "#e8ecff" },
|
|
33
|
+
lettering: { weight: 9, corner: "round", radius: 40, width: 1, gap: 18, slant: 0, cap: "round" },
|
|
34
|
+
},
|
|
35
|
+
ravelle: {
|
|
36
|
+
id: "ravelle",
|
|
37
|
+
name: "Ravelle",
|
|
38
|
+
genre: "motion",
|
|
39
|
+
note: "Nearest: the Nike swoosh, one tapered curve. Ravelle is a ball with two concentric arcs that taper at both ends and wrap the ball like a wake; it has no single wedge and no check shape.",
|
|
40
|
+
parts: [
|
|
41
|
+
part("b", "M49 46A17 17 0 1 0 83 46A17 17 0 1 0 49 46Z"),
|
|
42
|
+
part("a", "M61.1 73.6L59.1 73.7L57 73.5L54.9 73.2L52.9 72.6L50.9 71.9L48.9 71L47.1 69.9L45.2 68.7L43.5 67.4L41.9 65.9L40.4 64.2L39 62.5L37.8 60.6L36.7 58.6L35.8 56.5L35 54.4L34.5 52.2L34 50L33.8 47.7L33.8 45.4L33.9 43.2L34.2 40.9L34.7 38.7L35.4 36.5L36.2 34.4L37.2 32.4L38.3 30.4L39.6 28.6L41.1 26.9L42.6 25.3L44.3 23.9L46.1 22.6L47.9 21.4L49.8 20.4L51.8 19.6L53.8 18.9L55.9 18.5L58 18.2L60 18.1L62.1 18.3L62.1 18.3L60.3 19.2L58.5 20L56.8 21L55.2 22L53.7 23.1L52.2 24.2L50.9 25.5L49.7 26.8L48.5 28.2L47.4 29.6L46.5 31L45.6 32.6L44.9 34.1L44.2 35.7L43.6 37.3L43.2 38.9L42.8 40.6L42.5 42.2L42.3 43.9L42.3 45.6L42.3 47.3L42.4 48.9L42.6 50.6L42.9 52.3L43.3 53.9L43.8 55.5L44.5 57.1L45.2 58.7L46 60.3L46.9 61.8L47.9 63.2L49 64.6L50.2 66L51.5 67.3L52.9 68.5L54.4 69.6L55.9 70.7L57.6 71.7L59.3 72.6L61.1 73.6Z"),
|
|
43
|
+
part("a", "M50.6 84L48.3 83.7L46.1 83.1L43.9 82.4L41.7 81.4L39.6 80.4L37.6 79.1L35.6 77.8L33.7 76.3L31.9 74.7L30.2 73L28.6 71.1L27.2 69.2L25.8 67.1L24.6 65L23.5 62.7L22.5 60.5L21.7 58.1L21.1 55.7L20.6 53.3L20.3 50.8L20.1 48.3L20 45.8L20.2 43.4L20.5 40.9L20.9 38.5L21.5 36.1L22.3 33.7L23.2 31.4L24.2 29.2L25.4 27.1L26.7 25L28.1 23.1L29.7 21.2L31.3 19.5L33.1 17.9L34.9 16.4L36.8 15L38.8 13.8L40.9 12.8L43.1 12L43.1 12L41.7 13.8L40.3 15.6L39 17.3L37.7 19.1L36.6 20.9L35.5 22.7L34.6 24.6L33.7 26.5L33 28.4L32.3 30.3L31.7 32.2L31.2 34.1L30.8 36.1L30.4 38.1L30.2 40L30 42L29.9 43.9L30 45.9L30 47.8L30.2 49.8L30.4 51.7L30.8 53.6L31.2 55.5L31.7 57.4L32.2 59.3L32.9 61.2L33.6 63L34.4 64.8L35.3 66.6L36.3 68.4L37.3 70.1L38.5 71.8L39.7 73.5L41 75.1L42.5 76.7L43.9 78.2L45.5 79.7L47.2 81.1L48.9 82.5L50.6 84Z"),
|
|
44
|
+
],
|
|
45
|
+
light: { a: "#c41e6b", b: "#26262c", ink: "#26262c" },
|
|
46
|
+
dark: { a: "#ff5fa2", b: "#f1f1f4", ink: "#f6f6f8" },
|
|
47
|
+
lettering: { weight: 10, corner: "round", radius: 30, width: 1, gap: 12, slant: 10, cap: "round" },
|
|
48
|
+
},
|
|
49
|
+
kovreth: {
|
|
50
|
+
id: "kovreth",
|
|
51
|
+
name: "Kovreth",
|
|
52
|
+
genre: "monogram",
|
|
53
|
+
note: "Nearest: Fila, a letter in a box. Kovreth is a hexagon with the K cut out of it as negative space (a slit between the stem and the arms), in sunflower; the letter, the shape and the cut are all different.",
|
|
54
|
+
parts: [
|
|
55
|
+
part("a", "M45.7 6.5Q50 4 54.3 6.5L85.5 24.5Q89.8 27 89.8 32L89.8 68Q89.8 73 85.5 75.5L54.3 93.5Q50 96 45.7 93.5L14.5 75.5Q10.2 73 10.2 68L10.2 32Q10.2 27 14.5 24.5ZM30 29Q30 28 31 28L42 28Q43 28 43 29L43 71Q43 72 42 72L31 72Q30 72 30 71ZM47.7 50.8Q47 50 47.7 49.2L65.3 28.8Q66 28 67 28L80 28Q81 28 80.3 28.7L60.7 49.3Q60 50 60.7 50.7L80.3 71.3Q81 72 80 72L67 72Q66 72 65.3 71.2Z"),
|
|
56
|
+
],
|
|
57
|
+
light: { a: "#f2b21b", b: "#f2b21b", ink: "#221c0a" },
|
|
58
|
+
dark: { a: "#f2b21b", b: "#f2b21b", ink: "#fff5d6" },
|
|
59
|
+
lettering: { weight: 18, corner: "sharp", radius: 0, width: 0.7, gap: 5, slant: 0, cap: "butt" },
|
|
60
|
+
},
|
|
61
|
+
dunmar: {
|
|
62
|
+
id: "dunmar",
|
|
63
|
+
name: "Dunmar",
|
|
64
|
+
genre: "shield",
|
|
65
|
+
note: "Nearest: the shield badges that many kit makers and clubs use, with no single owner. Dunmar is a shield split down the middle, the right half set lower, with no letter, stripe or star, in claret and old gold.",
|
|
66
|
+
parts: [
|
|
67
|
+
part("a", "M11 10H48V94C28 84 11 72 11 50Z"),
|
|
68
|
+
part("b", "M52 18H89V50C89 72 72 84 52 94Z"),
|
|
69
|
+
],
|
|
70
|
+
light: { a: "#7a1f33", b: "#c9a24a", ink: "#4a1220" },
|
|
71
|
+
dark: { a: "#d6657d", b: "#e3c26e", ink: "#fbe9ee" },
|
|
72
|
+
lettering: { weight: 12, corner: "cut", radius: 14, width: 0.9, gap: 12, slant: 0, cap: "butt" },
|
|
73
|
+
},
|
|
74
|
+
ostrel: {
|
|
75
|
+
id: "ostrel",
|
|
76
|
+
name: "Ostrel",
|
|
77
|
+
genre: "disc",
|
|
78
|
+
note: "Nearest: The North Face, a half dome cut by curved lines. Ostrel is a whole disc cut by one straight diagonal gap into two offset pieces, in orange and navy.",
|
|
79
|
+
parts: [
|
|
80
|
+
part("a", "M20.1 73.5A42 42 0 1 1 92.2 31.9Z"),
|
|
81
|
+
part("b", "M16.6 81.5A42 42 0 0 0 87 40.9Z"),
|
|
82
|
+
],
|
|
83
|
+
light: { a: "#ee6a2c", b: "#141e3a", ink: "#141e3a" },
|
|
84
|
+
dark: { a: "#ff8a4d", b: "#8fa3d6", ink: "#f6efe9" },
|
|
85
|
+
lettering: { weight: 8, corner: "round", radius: 50, width: 1.1, gap: 22, slant: 0, cap: "round" },
|
|
86
|
+
},
|
|
87
|
+
vexlin: {
|
|
88
|
+
id: "vexlin",
|
|
89
|
+
name: "Vexlin",
|
|
90
|
+
genre: "geometry",
|
|
91
|
+
note: "Nearest: Umbro's double diamond and Hummel's chevrons, marks made of one repeated simple shape. Vexlin is three hexagons in a triangle, one a ring and one in the second colour, in violet and teal.",
|
|
92
|
+
parts: [
|
|
93
|
+
part("a", "M47.4 9.5Q50 8 52.6 9.5L65.6 17Q68.2 18.5 68.2 21.5L68.2 36.5Q68.2 39.5 65.6 41L52.6 48.5Q50 50 47.4 48.5L34.4 41Q31.8 39.5 31.8 36.5L31.8 21.5Q31.8 18.5 34.4 17ZM48.7 20.3Q50 19.5 51.3 20.3L56.9 23.5Q58.2 24.3 58.2 25.8L58.2 32.3Q58.2 33.8 56.9 34.5L51.3 37.8Q50 38.5 48.7 37.8L43.1 34.5Q41.8 33.8 41.8 32.3L41.8 25.8Q41.8 24.3 43.1 23.5Z"),
|
|
94
|
+
part("a", "M26.7 45.3Q29.3 43.8 31.9 45.3L44.9 52.8Q47.5 54.3 47.5 57.3L47.5 72.3Q47.5 75.3 44.9 76.8L31.9 84.3Q29.3 85.8 26.7 84.3L13.7 76.8Q11.1 75.3 11.1 72.3L11.1 57.3Q11.1 54.3 13.7 52.8Z"),
|
|
95
|
+
part("b", "M68.1 45.3Q70.7 43.8 73.3 45.3L86.3 52.8Q88.9 54.3 88.9 57.3L88.9 72.3Q88.9 75.3 86.3 76.8L73.3 84.3Q70.7 85.8 68.1 84.3L55.1 76.8Q52.5 75.3 52.5 72.3L52.5 57.3Q52.5 54.3 55.1 52.8Z"),
|
|
96
|
+
],
|
|
97
|
+
light: { a: "#5b2a86", b: "#19b6a2", ink: "#34195a" },
|
|
98
|
+
dark: { a: "#a77be0", b: "#36d6c0", ink: "#f1e9fb" },
|
|
99
|
+
lettering: { weight: 14, corner: "cut", radius: 18, width: 0.95, gap: 12, slant: 0, cap: "butt" },
|
|
100
|
+
},
|
|
101
|
+
quillan: {
|
|
102
|
+
id: "quillan",
|
|
103
|
+
name: "Quillan",
|
|
104
|
+
genre: "disc",
|
|
105
|
+
note: "Nearest: the BMW roundel, a circle in four quarters (not a sports mark). Quillan has convex quarter-discs set apart by a cross-shaped gap, one quarter smaller, with no ring, in teal and amber.",
|
|
106
|
+
parts: [
|
|
107
|
+
part("a", "M48 48L8 48A40 40 0 0 1 48 8Z"),
|
|
108
|
+
part("b", "M52 48L92 48A40 40 0 0 0 52 8Z"),
|
|
109
|
+
part("b", "M48 52L8 52A40 40 0 0 0 48 92Z"),
|
|
110
|
+
part("a", "M52 52L78 52A26 26 0 0 1 52 78Z"),
|
|
111
|
+
],
|
|
112
|
+
light: { a: "#12857f", b: "#f0b429", ink: "#0d4d49" },
|
|
113
|
+
dark: { a: "#3fc4bd", b: "#ffc94d", ink: "#e6f7f6" },
|
|
114
|
+
lettering: { weight: 10, corner: "round", radius: 20, width: 0.95, gap: 14, slant: 0, cap: "square" },
|
|
115
|
+
},
|
|
116
|
+
tenzar: {
|
|
117
|
+
id: "tenzar",
|
|
118
|
+
name: "Tenzar",
|
|
119
|
+
genre: "monogram",
|
|
120
|
+
note: "Nearest: the three-bar marks such as the Adidas performance logo. Tenzar is a Z of two level bars with bevelled ends joined by one diagonal slab in a second colour; the bars are not parallel and not three of a kind.",
|
|
121
|
+
parts: [
|
|
122
|
+
part("a", "M12 14Q12 12 14 12L86 12Q88 12 87.1 13.8L79.9 28.2Q79 30 77 30L14 30Q12 30 12 28Z"),
|
|
123
|
+
part("b", "M58.3 35.1Q60 34 62 34L86 34Q88 34 86.3 35.1L41.7 64.9Q40 66 38 66L14 66Q12 66 13.7 64.9Z"),
|
|
124
|
+
part("a", "M20.1 71.8Q21 70 23 70L86 70Q88 70 88 72L88 86Q88 88 86 88L14 88Q12 88 12.9 86.2Z"),
|
|
125
|
+
],
|
|
126
|
+
light: { a: "#10151d", b: "#14b7c9", ink: "#10151d" },
|
|
127
|
+
dark: { a: "#e9edf2", b: "#3fd4e4", ink: "#f2f5f8" },
|
|
128
|
+
lettering: { weight: 16, corner: "sharp", radius: 0, width: 1.1, gap: 10, slant: 14, cap: "butt" },
|
|
129
|
+
},
|
|
130
|
+
marenko: {
|
|
131
|
+
id: "marenko",
|
|
132
|
+
name: "Marenko",
|
|
133
|
+
genre: "geometry",
|
|
134
|
+
note: "Nearest: no sports maker that we know; the golden-ratio spiral is a common device in design. Marenko is four tiles, three of them quarter-discs, in gold and green.",
|
|
135
|
+
parts: [
|
|
136
|
+
part("a", "M60.1 77.5L5.1 77.5A55 55 0 0 1 60.1 22.5Z"),
|
|
137
|
+
part("b", "M63.1 54.3L63.1 22.5A31.8 31.8 0 0 1 94.9 54.3Z"),
|
|
138
|
+
part("a", "M74.7 57.3L94.9 57.3A20.2 20.2 0 0 1 74.7 77.5Z"),
|
|
139
|
+
part("b", "M63.1 57.3L71.7 57.3L71.7 77.5L63.1 77.5Z"),
|
|
140
|
+
],
|
|
141
|
+
light: { a: "#e0a100", b: "#1b8a5a", ink: "#3b2c00" },
|
|
142
|
+
dark: { a: "#f5c230", b: "#3fc78a", ink: "#fff4cc" },
|
|
143
|
+
lettering: { weight: 12, corner: "round", radius: 60, width: 0.9, gap: 14, slant: 0, cap: "round" },
|
|
144
|
+
},
|
|
145
|
+
halvane: {
|
|
146
|
+
id: "halvane",
|
|
147
|
+
name: "Halvane",
|
|
148
|
+
genre: "animal",
|
|
149
|
+
note: "Nearest: the Ram Trucks ram head (a vehicle maker, not sport) and clubs that are called Rams. Halvane is two spiral horns and a plain shield face, flat, in violet and yellow.",
|
|
150
|
+
parts: [
|
|
151
|
+
part("a", "M40.1 17.5L36.2 16.2L32.3 15.6L28.4 15.6L24.6 16.1L21 17.2L17.6 18.8L14.6 20.8L12 23.2L9.8 25.9L8 28.9L6.8 32L6 35.2L5.8 38.4L6 41.5L6.6 44.5L7.7 47.3L9.1 49.8L10.9 52.1L12.9 53.9L15.2 55.5L17.5 56.6L20 57.3L22.4 57.7L24.8 57.7L27.1 57.3L29.2 56.6L31.2 55.6L32.8 54.3L34.3 52.9L35.4 51.3L36.3 49.7L36.8 48L37.1 46.3L37.1 44.6L36.8 43.1L36.3 41.7L35.7 41.7L35.8 43L35.6 44.3L35.3 45.5L34.8 46.8L34.2 47.9L33.3 49L32.3 49.9L31.1 50.7L29.9 51.4L28.5 51.8L27.1 52.1L25.6 52.1L24.1 51.9L22.6 51.5L21.2 50.9L19.9 50.1L18.7 49L17.6 47.8L16.8 46.5L16.1 45L15.6 43.4L15.4 41.7L15.4 40L15.6 38.3L16.2 36.6L16.9 35L17.9 33.5L19.1 32.2L20.5 31L22.1 30L23.9 29.2L25.8 28.7L27.7 28.5L29.7 28.5L31.7 28.9L33.7 29.5L36.4 29.9L39.1 29.4L41.5 27.9L43.2 25.8L44 23.3L43.6 20.9L42.2 18.8ZM59.9 17.5L63.8 16.2L67.7 15.6L71.6 15.6L75.4 16.1L79 17.2L82.4 18.8L85.4 20.8L88 23.2L90.2 25.9L92 28.9L93.2 32L94 35.2L94.2 38.4L94 41.5L93.4 44.5L92.3 47.3L90.9 49.8L89.1 52.1L87.1 53.9L84.8 55.5L82.5 56.6L80 57.3L77.6 57.7L75.2 57.7L72.9 57.3L70.8 56.6L68.8 55.6L67.2 54.3L65.7 52.9L64.6 51.3L63.7 49.7L63.2 48L62.9 46.3L62.9 44.6L63.2 43.1L63.7 41.7L64.3 41.7L64.2 43L64.4 44.3L64.7 45.5L65.2 46.8L65.8 47.9L66.7 49L67.7 49.9L68.9 50.7L70.1 51.4L71.5 51.8L72.9 52.1L74.4 52.1L75.9 51.9L77.4 51.5L78.8 50.9L80.1 50.1L81.3 49L82.4 47.8L83.2 46.5L83.9 45L84.4 43.4L84.6 41.7L84.6 40L84.4 38.3L83.8 36.6L83.1 35L82.1 33.5L80.9 32.2L79.5 31L77.9 30L76.1 29.2L74.2 28.7L72.3 28.5L70.3 28.5L68.3 28.9L66.3 29.5L63.6 29.9L60.9 29.4L58.5 27.9L56.8 25.8L56 23.3L56.4 20.9L57.8 18.8Z"),
|
|
152
|
+
part("b", "M42 29Q50 23 58 29L58 54Q57 72 50 86Q43 72 42 54Z"),
|
|
153
|
+
],
|
|
154
|
+
light: { a: "#3a2a8c", b: "#f4b400", ink: "#231a5c" },
|
|
155
|
+
dark: { a: "#8f7df0", b: "#ffcb33", ink: "#efeaff" },
|
|
156
|
+
lettering: { weight: 7, corner: "sharp", radius: 0, width: 1, gap: 20, slant: 0, cap: "butt" },
|
|
157
|
+
},
|
|
158
|
+
solvik: {
|
|
159
|
+
id: "solvik",
|
|
160
|
+
name: "Solvik",
|
|
161
|
+
genre: "ball",
|
|
162
|
+
note: "Nearest: the everyday tennis-ball icon, a disc with two seam curves, which is a generic symbol and not any maker's mark. Solvik is a lime disc with two crescent seams cut out, and nothing else.",
|
|
163
|
+
parts: [
|
|
164
|
+
part("a", "M7 50A43 43 0 1 0 93 50A43 43 0 1 0 7 50ZM26 22C52 38 52 62 26 78C44 62 44 38 26 22ZM74 22C48 38 48 62 74 78C56 62 56 38 74 22Z"),
|
|
165
|
+
],
|
|
166
|
+
light: { a: "#9bc41c", b: "#9bc41c", ink: "#2a3306" },
|
|
167
|
+
dark: { a: "#b6e03a", b: "#b6e03a", ink: "#f3fbd6" },
|
|
168
|
+
lettering: { weight: 13, corner: "round", radius: 16, width: 0.85, gap: 12, slant: 0, cap: "round" },
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
export const TEAMS = Object.freeze({
|
|
172
|
+
saltmere: {
|
|
173
|
+
id: "saltmere",
|
|
174
|
+
city: "Saltmere",
|
|
175
|
+
nickname: "Gulls",
|
|
176
|
+
genre: "roundel",
|
|
177
|
+
note: "Nearest: a club that wears a whole seagull. This one is a roundel: a gull's wings cut out of the sky over a wave line.",
|
|
178
|
+
parts: [
|
|
179
|
+
part("a", "M4 50A46 46 0 1 0 96 50A46 46 0 1 0 4 50ZM9.5 50A40.5 40.5 0 1 0 90.5 50A40.5 40.5 0 1 0 9.5 50Z"),
|
|
180
|
+
part("b", "M17.1 62A35 35 0 1 1 82.9 62C72 55 62 69 50 62C38 55 28 69 17.1 62ZM26 40Q38 22 50 38Q62 22 74 40Q62 33 50 48Q38 33 26 40Z"),
|
|
181
|
+
part("a", "M19.4 67C28 60 38 74 50 67C62 74 72 60 80.6 67A35 35 0 0 1 19.4 67Z"),
|
|
182
|
+
],
|
|
183
|
+
light: { a: "#0e4a6b", b: "#8fd0e8", c: "#ffffff" },
|
|
184
|
+
dark: { a: "#3b9bc4", b: "#a9dff0", c: "#ffffff" },
|
|
185
|
+
},
|
|
186
|
+
greywick: {
|
|
187
|
+
id: "greywick",
|
|
188
|
+
city: "Greywick",
|
|
189
|
+
nickname: "Wardens",
|
|
190
|
+
genre: "crest",
|
|
191
|
+
note: "Nearest: the many castle-on-a-shield crests. This is a plain shield under a red chief with a tower cut out.",
|
|
192
|
+
parts: [
|
|
193
|
+
part("b", "M12 10L88 10L88 25L12 25Z"),
|
|
194
|
+
part("a", "M12 30H88V50C88 72 70 86 50 95C30 86 12 72 12 50ZM34 80L34 46L34 40L40 40L40 46L45 46L45 40L55 40L55 46L60 46L60 40L66 40L66 46L66 80ZM45 80V66Q50 58 55 66V80Z"),
|
|
195
|
+
],
|
|
196
|
+
light: { a: "#4a4f57", b: "#c8372d", c: "#ffffff" },
|
|
197
|
+
dark: { a: "#aeb6c2", b: "#e5594d", c: "#ffffff" },
|
|
198
|
+
},
|
|
199
|
+
brightwater: {
|
|
200
|
+
id: "brightwater",
|
|
201
|
+
city: "Brightwater",
|
|
202
|
+
nickname: "Comets",
|
|
203
|
+
genre: "monogram",
|
|
204
|
+
note: "Nearest: letter-in-a-disc club badges. A B knocked out of a violet disc, with a gold arc for the comet.",
|
|
205
|
+
parts: [
|
|
206
|
+
part("a", "M14 50A36 36 0 1 0 86 50A36 36 0 1 0 14 50ZM34 29Q34 26 37 26L53 26Q56 26 58.7 27.3L65.3 30.7Q68 32 68 35L68 42Q68 45 65.9 47.1L65.1 47.9Q63 50 65.3 52L67.7 54Q70 56 70 59L70 65Q70 68 67.5 69.7L60.5 74.3Q58 76 55 76L37 76Q34 76 34 73ZM44 36.5Q44 35 45.5 35L52.5 35Q54 35 55.2 35.9L56.8 37.1Q58 38 58 39.5L58 41.5Q58 43 56.8 43.9L55.2 45.1Q54 46 52.5 46L45.5 46Q44 46 44 44.5ZM44 56.5Q44 55 45.5 55L53.5 55Q55 55 56.2 55.9L58.8 58.1Q60 59 60 60.5L60 62.5Q60 64 58.8 64.9L56.2 67.1Q55 68 53.5 68L45.5 68Q44 68 44 66.5Z"),
|
|
207
|
+
part("b", "M9.6 35.3L10.3 31.9L11.5 28.7L13 25.5L14.7 22.4L16.8 19.5L19 16.8L21.6 14.3L24.3 11.9L27.3 9.8L30.4 7.9L33.7 6.3L37.1 5L40.6 4L44.3 3.2L47.9 2.8L51.7 2.7L55.4 2.9L59.1 3.4L62.7 4.2L66.2 5.4L69.7 6.8L73 8.5L76.2 10.5L79.1 12.7L81.9 15.2L84.4 17.9L86.8 20.8L88.8 23.8L90.6 27L92.1 30.4L93.3 33.8L94.2 37.3L94.8 40.9L95.1 44.5L95 48L94.7 51.6L94.1 55L93.2 58.4L92 61.6L90.4 64.7L90.4 64.7L90.9 61.3L91.2 58L91.3 54.7L91.2 51.4L90.9 48.2L90.3 45.1L89.5 42L88.5 39L87.3 36.1L85.9 33.3L84.3 30.6L82.5 28.1L80.6 25.7L78.4 23.5L76.2 21.4L73.8 19.5L71.3 17.8L68.7 16.3L66 15L63.2 13.8L60.3 12.9L57.4 12.2L54.4 11.6L51.3 11.3L48.3 11.3L45.3 11.4L42.2 11.7L39.2 12.3L36.2 13.1L33.3 14.1L30.4 15.3L27.6 16.8L24.9 18.4L22.3 20.3L19.8 22.4L17.5 24.6L15.3 27L13.3 29.6L11.4 32.4L9.6 35.3Z"),
|
|
208
|
+
],
|
|
209
|
+
light: { a: "#7a2a8e", b: "#f2b705", c: "#ffffff" },
|
|
210
|
+
dark: { a: "#b46ad0", b: "#ffc933", c: "#ffffff" },
|
|
211
|
+
},
|
|
212
|
+
cinderfell: {
|
|
213
|
+
id: "cinderfell",
|
|
214
|
+
city: "Cinderfell",
|
|
215
|
+
nickname: "Bears",
|
|
216
|
+
genre: "mascot",
|
|
217
|
+
note: "Nearest: the Memphis Grizzlies' bear head. This one is a flat front view built from circles, with an angry brow.",
|
|
218
|
+
parts: [
|
|
219
|
+
part("a", "M11 28A13 13 0 1 0 37 28A13 13 0 1 0 11 28Z"),
|
|
220
|
+
part("a", "M63 28A13 13 0 1 0 89 28A13 13 0 1 0 63 28Z"),
|
|
221
|
+
part("a", "M16 56A34 34 0 1 0 84 56A34 34 0 1 0 16 56ZM30 47Q30 46 30.9 46.4L43.1 51.6Q44 52 43.7 52.9L42.3 57.1Q42 58 41.1 57.7L30.9 54.3Q30 54 30 53ZM70 47Q70 46 69.1 46.4L56.9 51.6Q56 52 56.3 52.9L57.7 57.1Q58 58 58.9 57.7L69.1 54.3Q70 54 70 53ZM31 70Q50 52 69 70Q66 88 50 90Q34 88 31 70Z"),
|
|
222
|
+
part("c", "M35 71Q50 58 65 71Q63 85 50 87Q37 85 35 71ZM43 69Q50 64 57 69Q56 76 50 77Q44 76 43 69Z"),
|
|
223
|
+
],
|
|
224
|
+
light: { a: "#5a3a24", b: "#d9b27c", c: "#d9b27c" },
|
|
225
|
+
dark: { a: "#c08a5c", b: "#f0d4aa", c: "#f0d4aa" },
|
|
226
|
+
},
|
|
227
|
+
valmere: {
|
|
228
|
+
id: "valmere",
|
|
229
|
+
city: "Valmere",
|
|
230
|
+
nickname: "Hawks",
|
|
231
|
+
genre: "mascot",
|
|
232
|
+
note: "Nearest: the Atlanta Hawks' hawk head. This one is a faceted head in profile, in navy and amber.",
|
|
233
|
+
parts: [
|
|
234
|
+
part("a", "M15.2 94Q14 94 13.9 92.8L10.1 59.2Q10 58 10.3 56.8L17.7 31.2Q18 30 18.9 29.2L35.1 14.8Q36 14 37.2 13.7L58.8 8.3Q60 8 61.1 8.5L76.9 15.5Q78 16 78.7 16.9L85.3 25.1Q86 26 85 26.6L73 33.4Q72 34 72.1 35.2L72.9 48.8Q73 50 72.1 50.8L64.9 57.2Q64 58 64 59.2L64 68.8Q64 70 64.7 71L71.3 81Q72 82 71 82.7L59 91.3Q58 92 57.2 91.1L48.8 80.9Q48 80 47.2 80.9L36.8 93.1Q36 94 34.8 94ZM44 24L64 26L55 36Z"),
|
|
235
|
+
part("b", "M87 26.7Q88 26 88.6 27L96.4 41Q97 42 96.9 43.2L95.1 58.8Q95 60 94.2 59.1L86.8 50.9Q86 50 84.8 50L77.2 50Q76 50 75.9 48.8L75.1 37.2Q75 36 76 35.3Z"),
|
|
236
|
+
],
|
|
237
|
+
light: { a: "#1f3b6f", b: "#f2a900", c: "#ffffff" },
|
|
238
|
+
dark: { a: "#6f95e0", b: "#ffc233", c: "#ffffff" },
|
|
239
|
+
},
|
|
240
|
+
larkmoor: {
|
|
241
|
+
id: "larkmoor",
|
|
242
|
+
city: "Larkmoor",
|
|
243
|
+
nickname: "Foxes",
|
|
244
|
+
genre: "mascot",
|
|
245
|
+
note: "Nearest: the Fox Racing head and the Leicester City fox. This is a front-facing fox made of seven flat facets.",
|
|
246
|
+
parts: [
|
|
247
|
+
part("a", "M9.9 7.5Q10 6 11.2 6.9L36.8 27.1Q38 28 39.5 28L60.5 28Q62 28 63.2 27.1L88.8 6.9Q90 6 90.1 7.5L93.9 48.5Q94 50 92.6 50.4L67.4 57.6Q66 58 64.8 57.1L51.2 46.9Q50 46 48.8 46.9L35.2 57.1Q34 58 32.6 57.6L7.4 50.4Q6 50 6.1 48.5ZM22 38L38 40L30 47ZM78 38L62 40L70 47Z"),
|
|
248
|
+
part("b", "M9.6 57Q8.5 56 9.9 56.4L32.6 63.6Q34 64 35.2 63.1L48.8 52.9Q50 52 51.2 52.9L64.8 63.1Q66 64 67.4 63.6L90.1 56.4Q91.5 56 90.4 57L51.1 94Q50 95 48.9 94Z"),
|
|
249
|
+
part("c", "M42.6 82.8Q42 82 43 82L57 82Q58 82 57.4 82.8L50.6 91.2Q50 92 49.4 91.2Z"),
|
|
250
|
+
],
|
|
251
|
+
light: { a: "#d4561e", b: "#f4ead8", c: "#1c1c1c" },
|
|
252
|
+
dark: { a: "#f07a3d", b: "#f4ead8", c: "#ffd9c2" },
|
|
253
|
+
},
|
|
254
|
+
ironport: {
|
|
255
|
+
id: "ironport",
|
|
256
|
+
city: "Ironport",
|
|
257
|
+
nickname: "Sharks",
|
|
258
|
+
genre: "emblem",
|
|
259
|
+
note: "Nearest: the San Jose Sharks' leaping shark. This one is only a fin, in a ring, over two wave bars.",
|
|
260
|
+
parts: [
|
|
261
|
+
part("c", "M4 50A46 46 0 1 0 96 50A46 46 0 1 0 4 50ZM9 50A41 41 0 1 0 91 50A41 41 0 1 0 9 50Z"),
|
|
262
|
+
part("a", "M86 72C76 54 62 30 40 8C46 30 40 54 24 72Z"),
|
|
263
|
+
part("b", "M18.3 76C34 70 42 82 50 76C58 70 66 82 81.7 76L74.3 83C66 89 58 77 50 83C42 89 34 77 25.7 83Z"),
|
|
264
|
+
part("b", "M32.3 87C34 81 42 93 50 87C58 81 66 93 67.7 87L50 91C66 97 58 85 50 91C42 97 34 85 50 91Z"),
|
|
265
|
+
],
|
|
266
|
+
light: { a: "#233447", b: "#2fa4b8", c: "#9aa7b4" },
|
|
267
|
+
dark: { a: "#7f9bb8", b: "#3fc2d6", c: "#b8c4d0" },
|
|
268
|
+
},
|
|
269
|
+
pinecrest: {
|
|
270
|
+
id: "pinecrest",
|
|
271
|
+
city: "Pinecrest",
|
|
272
|
+
nickname: "Firs",
|
|
273
|
+
genre: "badge",
|
|
274
|
+
note: "Nearest: forestry and outdoor badges; no well-known club uses a fir. Three stacked triangles cut out of a rounded square.",
|
|
275
|
+
parts: [
|
|
276
|
+
part("a", "M10 24Q10 10 24 10L76 10Q90 10 90 24L90 76Q90 90 76 90L24 90Q10 90 10 76ZM49.6 18.7Q50 18 50.4 18.7L61.6 37.3Q62 38 61.2 38L38.8 38Q38 38 38.4 37.3ZM49.5 32.6Q50 32 50.5 32.6L67.5 53.4Q68 54 67.2 54L32.8 54Q32 54 32.5 53.4ZM49.4 48.6Q50 48 50.6 48.6L73.4 71.4Q74 72 73.2 72L26.8 72Q26 72 26.6 71.4Z"),
|
|
277
|
+
part("b", "M45 74L55 74L55 84L45 84Z"),
|
|
278
|
+
],
|
|
279
|
+
light: { a: "#14573a", b: "#8a5a2b", c: "#ffffff" },
|
|
280
|
+
dark: { a: "#3fae7c", b: "#c58b4a", c: "#ffffff" },
|
|
281
|
+
},
|
|
282
|
+
redfern: {
|
|
283
|
+
id: "redfern",
|
|
284
|
+
city: "Redfern",
|
|
285
|
+
nickname: "Rovers",
|
|
286
|
+
genre: "crest",
|
|
287
|
+
note: "Nearest: the Dallas Cowboys' star. This is a gold star set inside a red diamond ring.",
|
|
288
|
+
parts: [
|
|
289
|
+
part("a", "M46.5 7.5Q50 4 53.5 7.5L92.5 46.5Q96 50 92.5 53.5L53.5 92.5Q50 96 46.5 92.5L7.5 53.5Q4 50 7.5 46.5ZM48.6 15.4Q50 14 51.4 15.4L84.6 48.6Q86 50 84.6 51.4L51.4 84.6Q50 86 48.6 84.6L15.4 51.4Q14 50 15.4 48.6Z"),
|
|
290
|
+
part("b", "M49.5 29.4Q50 28 50.5 29.4L55.4 42.5Q55.9 43.9 57.4 44L71.3 44.5Q72.8 44.6 71.6 45.5L60.7 54.2Q59.5 55.1 59.9 56.5L63.7 70Q64.1 71.4 62.9 70.6L51.2 62.8Q50 62 48.8 62.8L37.1 70.6Q35.9 71.4 36.3 70L40.1 56.5Q40.5 55.1 39.3 54.2L28.4 45.5Q27.2 44.6 28.7 44.5L42.6 44Q44.1 43.9 44.6 42.5Z"),
|
|
291
|
+
],
|
|
292
|
+
light: { a: "#b01e2e", b: "#f0c24b", c: "#ffffff" },
|
|
293
|
+
dark: { a: "#e4505f", b: "#f6cf63", c: "#ffffff" },
|
|
294
|
+
},
|
|
295
|
+
tarn: {
|
|
296
|
+
id: "tarn",
|
|
297
|
+
city: "Tarn Valley",
|
|
298
|
+
nickname: "Peaks",
|
|
299
|
+
genre: "badge",
|
|
300
|
+
note: "Nearest: Patagonia's skyline and The North Face's half dome. Two cut-out peaks and a sun in a hexagon.",
|
|
301
|
+
parts: [
|
|
302
|
+
part("a", "M45.7 6.5Q50 4 54.3 6.5L85.5 24.5Q89.8 27 89.8 32L89.8 68Q89.8 73 85.5 75.5L54.3 93.5Q50 96 45.7 93.5L14.5 75.5Q10.2 73 10.2 68L10.2 32Q10.2 27 14.5 24.5ZM17 70Q16 70 16.6 69.2L39.4 34.8Q40 34 40.6 34.8L63.4 69.2Q64 70 63 70ZM45 70Q44 70 44.6 69.2L65.4 42.8Q66 42 66.6 42.8L87.4 69.2Q88 70 87 70Z"),
|
|
303
|
+
part("b", "M60 28A8 8 0 1 0 76 28A8 8 0 1 0 60 28Z"),
|
|
304
|
+
],
|
|
305
|
+
light: { a: "#26527a", b: "#f2c14e", c: "#ffffff" },
|
|
306
|
+
dark: { a: "#5f9bd0", b: "#f6cf63", c: "#ffffff" },
|
|
307
|
+
},
|
|
308
|
+
});
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** How a wordmark is lettered. */
|
|
2
|
+
export interface LetterStyle {
|
|
3
|
+
/** Stroke weight, in units of a letter 100 high. */
|
|
4
|
+
weight: number;
|
|
5
|
+
/** Corner treatment: `round` (a curve), `cut` (a straight cut) or `sharp`. */
|
|
6
|
+
corner: "round" | "cut" | "sharp";
|
|
7
|
+
/** The size of the corner, in the same units. */
|
|
8
|
+
radius: number;
|
|
9
|
+
/** Width of a letter, 1 being 60 units across. */
|
|
10
|
+
width: number;
|
|
11
|
+
/** Space between letters, in the same units. */
|
|
12
|
+
gap: number;
|
|
13
|
+
/** Lean to the right, in degrees (negative leans left). */
|
|
14
|
+
slant: number;
|
|
15
|
+
/** The ends of a stroke. */
|
|
16
|
+
cap: "butt" | "round" | "square";
|
|
17
|
+
}
|
|
18
|
+
/** The letters the alphabet draws. */
|
|
19
|
+
export declare const LETTERS: readonly string[];
|
|
20
|
+
/** A word laid out: the path of all its letters (stroked, not filled) and the box it fills. */
|
|
21
|
+
export interface Lettering {
|
|
22
|
+
d: string;
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
/** The stroke weight the path is to be drawn with. */
|
|
26
|
+
weight: number;
|
|
27
|
+
}
|
|
28
|
+
/** The unit height the lettering is drawn at. */
|
|
29
|
+
export declare const LETTER_HEIGHT = 100;
|
|
30
|
+
/** A word in capitals, in a style. A letter the alphabet does not have is left out. The box includes the stroke's half weight and the room a lean needs. */
|
|
31
|
+
export declare function lettering(word: string, style: LetterStyle): Lettering;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// The lettering of the maker wordmarks: our own alphabet of capitals, drawn as strokes. Each letter is a few polylines on a unit box (x across, y down, 0 to 1); a style sets the weight, how the corners are
|
|
2
|
+
// treated (sharp, rounded or cut), the width, the spacing, the slant and the line ends, so that each maker's wordmark has a lettering of its own from one set of skeletons. It is not a copy of any typeface.
|
|
3
|
+
const BOX = [[0, 0], [1, 0], [1, 1], [0, 1]];
|
|
4
|
+
const SKELETONS = {
|
|
5
|
+
A: { strokes: [[[0, 1], [0.5, 0], [1, 1]], [[0.2, 0.68], [0.8, 0.68]]], wide: 1.1 },
|
|
6
|
+
B: { strokes: [[[0, 0], [0, 1]], [[0, 0], [0.88, 0], [0.88, 0.5], [0, 0.5]], [[0.88, 0.5], [1, 0.5], [1, 1], [0, 1]]] },
|
|
7
|
+
C: { strokes: [[[1, 0], [0, 0], [0, 1], [1, 1]]] },
|
|
8
|
+
D: { strokes: [[[0, 0], [0.62, 0], [1, 0.34], [1, 0.66], [0.62, 1], [0, 1]]], closed: [0] },
|
|
9
|
+
E: { strokes: [[[1, 0], [0, 0], [0, 1], [1, 1]], [[0, 0.5], [0.8, 0.5]]] },
|
|
10
|
+
F: { strokes: [[[1, 0], [0, 0], [0, 1]], [[0, 0.5], [0.8, 0.5]]] },
|
|
11
|
+
G: { strokes: [[[1, 0.16], [1, 0], [0, 0], [0, 1], [1, 1], [1, 0.55], [0.55, 0.55]]] },
|
|
12
|
+
H: { strokes: [[[0, 0], [0, 1]], [[1, 0], [1, 1]], [[0, 0.5], [1, 0.5]]] },
|
|
13
|
+
I: { strokes: [[[0.5, 0], [0.5, 1]]], wide: 0 },
|
|
14
|
+
J: { strokes: [[[1, 0], [1, 0.78], [0.78, 1], [0.22, 1], [0, 0.78]]] },
|
|
15
|
+
K: { strokes: [[[0, 0], [0, 1]], [[1, 0], [0.08, 0.56], [1, 1]]] },
|
|
16
|
+
L: { strokes: [[[0, 0], [0, 1], [1, 1]]] },
|
|
17
|
+
M: { strokes: [[[0, 1], [0, 0], [0.5, 0.62], [1, 0], [1, 1]]], wide: 1.3 },
|
|
18
|
+
N: { strokes: [[[0, 1], [0, 0], [1, 1], [1, 0]]] },
|
|
19
|
+
O: { strokes: [BOX], closed: [0] },
|
|
20
|
+
P: { strokes: [[[0, 1], [0, 0], [1, 0], [1, 0.55], [0, 0.55]]] },
|
|
21
|
+
Q: { strokes: [BOX, [[0.6, 0.62], [1, 1]]], closed: [0] },
|
|
22
|
+
R: { strokes: [[[0, 1], [0, 0], [1, 0], [1, 0.5], [0, 0.5]], [[0.44, 0.5], [1, 1]]] },
|
|
23
|
+
S: { strokes: [[[1, 0], [0, 0], [0, 0.5], [1, 0.5], [1, 1], [0, 1]]] },
|
|
24
|
+
T: { strokes: [[[0, 0], [1, 0]], [[0.5, 0], [0.5, 1]]] },
|
|
25
|
+
U: { strokes: [[[0, 0], [0, 1], [1, 1], [1, 0]]] },
|
|
26
|
+
V: { strokes: [[[0, 0], [0.5, 1], [1, 0]]], wide: 1.1 },
|
|
27
|
+
W: { strokes: [[[0, 0], [0.25, 1], [0.5, 0.3], [0.75, 1], [1, 0]]], wide: 1.5 },
|
|
28
|
+
X: { strokes: [[[0, 0], [1, 1]], [[1, 0], [0, 1]]], wide: 1.05 },
|
|
29
|
+
Y: { strokes: [[[0, 0], [0.5, 0.5], [1, 0]], [[0.5, 0.5], [0.5, 1]]] },
|
|
30
|
+
Z: { strokes: [[[0, 0], [1, 0], [0, 1], [1, 1]]] },
|
|
31
|
+
};
|
|
32
|
+
/** Letters whose right side is open at the top or the bottom, and letters whose sides lean in: a pair of the two is set closer. */
|
|
33
|
+
const OPEN = "LTFPYRVAW";
|
|
34
|
+
const LEAN = "AVWYT";
|
|
35
|
+
/** The letters the alphabet draws. */
|
|
36
|
+
export const LETTERS = Object.freeze(Object.keys(SKELETONS));
|
|
37
|
+
const round1 = (value) => String(Math.round(value * 10) / 10 + 0);
|
|
38
|
+
/** One stroke as a path: corners rounded or cut by `radius`, never by more than half a side. */
|
|
39
|
+
function strokePath(points, closed, style) {
|
|
40
|
+
const n = points.length;
|
|
41
|
+
let d = "";
|
|
42
|
+
for (let i = 0; i < n; i++) {
|
|
43
|
+
const p = points[i];
|
|
44
|
+
const end = !closed && (i === 0 || i === n - 1);
|
|
45
|
+
if (end || style.corner === "sharp" || style.radius <= 0) {
|
|
46
|
+
d += `${i === 0 ? "M" : "L"}${round1(p[0])} ${round1(p[1])}`;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
const a = points[(i + n - 1) % n];
|
|
50
|
+
const b = points[(i + 1) % n];
|
|
51
|
+
const l1 = Math.hypot(a[0] - p[0], a[1] - p[1]);
|
|
52
|
+
const l2 = Math.hypot(b[0] - p[0], b[1] - p[1]);
|
|
53
|
+
const t1 = Math.min(style.radius / l1, 0.5);
|
|
54
|
+
const t2 = Math.min(style.radius / l2, 0.5);
|
|
55
|
+
const s = [p[0] + (a[0] - p[0]) * t1, p[1] + (a[1] - p[1]) * t1];
|
|
56
|
+
const e = [p[0] + (b[0] - p[0]) * t2, p[1] + (b[1] - p[1]) * t2];
|
|
57
|
+
d += `${i === 0 ? "M" : "L"}${round1(s[0])} ${round1(s[1])}`;
|
|
58
|
+
d += style.corner === "round" ? `Q${round1(p[0])} ${round1(p[1])} ${round1(e[0])} ${round1(e[1])}` : `L${round1(e[0])} ${round1(e[1])}`;
|
|
59
|
+
}
|
|
60
|
+
return closed ? `${d}Z` : d;
|
|
61
|
+
}
|
|
62
|
+
/** The unit height the lettering is drawn at. */
|
|
63
|
+
export const LETTER_HEIGHT = 100;
|
|
64
|
+
/** A word in capitals, in a style. A letter the alphabet does not have is left out. The box includes the stroke's half weight and the room a lean needs. */
|
|
65
|
+
export function lettering(word, style) {
|
|
66
|
+
const lean = Math.tan((style.slant * Math.PI) / 180);
|
|
67
|
+
const half = style.weight / 2;
|
|
68
|
+
const top = half + (style.cap === "square" ? half : 0);
|
|
69
|
+
const pad = half + (style.cap === "square" ? half * 0.42 : 0) + Math.abs(lean) * (LETTER_HEIGHT / 2);
|
|
70
|
+
let x = pad;
|
|
71
|
+
let before = "";
|
|
72
|
+
const parts = [];
|
|
73
|
+
for (const char of word.toUpperCase()) {
|
|
74
|
+
const skeleton = SKELETONS[char];
|
|
75
|
+
if (skeleton === undefined)
|
|
76
|
+
continue;
|
|
77
|
+
const w = 60 * style.width * (skeleton.wide ?? 1);
|
|
78
|
+
if (before !== "" && OPEN.includes(before) && LEAN.includes(char) && before !== char)
|
|
79
|
+
x -= 0.3 * 60 * style.width;
|
|
80
|
+
before = char;
|
|
81
|
+
skeleton.strokes.forEach((stroke, index) => {
|
|
82
|
+
const points = stroke.map(([u, v]) => [x + u * w + (LETTER_HEIGHT / 2 - v * LETTER_HEIGHT) * lean, top + v * LETTER_HEIGHT]);
|
|
83
|
+
parts.push(strokePath(points, skeleton.closed?.includes(index) === true, style));
|
|
84
|
+
});
|
|
85
|
+
x += w + style.weight + style.gap;
|
|
86
|
+
}
|
|
87
|
+
return { d: parts.join(""), width: x - style.gap - style.weight + pad, height: LETTER_HEIGHT + 2 * top, weight: style.weight };
|
|
88
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type MakerId, type TeamId } from "./brand.data.ts";
|
|
2
|
+
/** What a maker's logo is made of: its mark alone (the default), its wordmark alone, the two side by side or the wordmark under the mark. */
|
|
3
|
+
export type LogoLayout = "mark" | "wordmark" | "horizontal" | "stacked";
|
|
4
|
+
/** The options every logo takes. */
|
|
5
|
+
export interface LogoOptions {
|
|
6
|
+
/** `"full"` (the default) draws the logo in its own colours; `"mono"` draws it in one colour, `ink`. */
|
|
7
|
+
color?: "full" | "mono";
|
|
8
|
+
/** The colours of the logo for a light page (the default) or a dark one. */
|
|
9
|
+
theme?: "light" | "dark";
|
|
10
|
+
/** The one colour of a `"mono"` logo: `#rgb`, `#rrggbb` or `rgb()`. By default `currentColor`, so the logo takes the page's text colour. Ignored by a full-colour logo. */
|
|
11
|
+
ink?: string;
|
|
12
|
+
/** The height in pixels (64 by default); the width follows the layout. The drawing is a vector at any size. */
|
|
13
|
+
size?: number;
|
|
14
|
+
/** The `<title>`: a string writes that title (escaped), `false` drops it and marks the drawing `aria-hidden="true"`. By default the maker's name or the team's name. */
|
|
15
|
+
title?: string | false;
|
|
16
|
+
}
|
|
17
|
+
/** The options of a maker's logo. */
|
|
18
|
+
export interface MakerLogoOptions extends LogoOptions {
|
|
19
|
+
/** Which parts to draw. By default only the mark: the name is optional. */
|
|
20
|
+
layout?: LogoLayout;
|
|
21
|
+
}
|
|
22
|
+
/** Where a logo goes inside another drawing: its top left corner and its height, in that drawing's units. */
|
|
23
|
+
export interface LogoPlace {
|
|
24
|
+
x?: number;
|
|
25
|
+
y?: number;
|
|
26
|
+
/** The height of the logo in the drawing's units (100 by default). */
|
|
27
|
+
size?: number;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* A fictional maker's logo as an SVG document: its mark by default, or its wordmark, or both (`layout`). In its own colours for a light or a dark page, or in one colour (`color: "mono"`, `ink`).
|
|
31
|
+
* @example
|
|
32
|
+
* ```ts
|
|
33
|
+
* import { makerLogo } from "@johnmorrisdotca/dougu-sports/brands";
|
|
34
|
+
* const svg = makerLogo("arvane", { size: 48 });
|
|
35
|
+
* console.log(svg.startsWith("<svg"), svg.includes("<title>Arvane</title>"));
|
|
36
|
+
* // true true
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function makerLogo(id: MakerId, o?: MakerLogoOptions): string;
|
|
40
|
+
/** A fictional team's logo as an SVG document, in its own colours for a light or a dark page, or in one colour. */
|
|
41
|
+
export declare function teamLogo(id: TeamId, o?: LogoOptions): string;
|
|
42
|
+
/**
|
|
43
|
+
* A maker's logo as a `<g>` to put inside another SVG: a jersey, a cap, a T-shirt, a card. It has no id, no gradient and no `<title>`, so any number of them can sit in one document. `x`, `y` and `size` place it in that drawing's units.
|
|
44
|
+
*/
|
|
45
|
+
export declare function makerLogoGroup(id: MakerId, place?: LogoPlace, o?: Omit<MakerLogoOptions, "size" | "title">): string;
|
|
46
|
+
/** A team's logo as a `<g>` to put inside another SVG (see `makerLogoGroup`). */
|
|
47
|
+
export declare function teamLogoGroup(id: TeamId, place?: LogoPlace, o?: Omit<LogoOptions, "size" | "title">): string;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// Draws the fictional logos: a maker's mark, its wordmark or both, and a team's logo, as an SVG document or as a group to place inside another drawing. A pure function of its options: the same id and options give the same
|
|
2
|
+
// string, there are no ids, no gradients and no filters, and a colour that is not `#rgb`, `#rrggbb` or `rgb()` is ignored.
|
|
3
|
+
import { escape, hexOf, readColour } from "../emblems/emblem.core.js";
|
|
4
|
+
import { LETTER_HEIGHT, lettering } from "./brand.letters.js";
|
|
5
|
+
import { MAKERS, TEAMS } from "./brand.data.js";
|
|
6
|
+
const MARK = 100;
|
|
7
|
+
const r2 = (value) => Math.round(value * 100) / 100;
|
|
8
|
+
const r4 = (value) => Math.round(value * 10000) / 10000;
|
|
9
|
+
const HORIZONTAL_GAP = 16;
|
|
10
|
+
const WORD_HEIGHT_BESIDE = 34;
|
|
11
|
+
const STACK_GAP = 12;
|
|
12
|
+
const clampSize = (value, fallback) => (typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.min(value, 4096) : fallback);
|
|
13
|
+
/** The colour of a mono logo: a colour that reads, or `currentColor`. */
|
|
14
|
+
function monoInk(ink) {
|
|
15
|
+
const rgb = readColour(ink);
|
|
16
|
+
return rgb === undefined ? "currentColor" : hexOf(rgb);
|
|
17
|
+
}
|
|
18
|
+
const partsMarkup = (parts, colorOf) => parts.map((part) => `<path fill="${colorOf(part)}" fill-rule="evenodd" d="${part.d}"/>`).join("");
|
|
19
|
+
function makerBody(maker, layout, o) {
|
|
20
|
+
const mono = o?.color === "mono";
|
|
21
|
+
const palette = o?.theme === "dark" ? maker.dark : maker.light;
|
|
22
|
+
const ink = monoInk(o?.ink);
|
|
23
|
+
const mark = partsMarkup(maker.parts, (part) => (mono ? ink : part.role === "a" ? palette.a : palette.b));
|
|
24
|
+
const word = lettering(maker.name, maker.lettering);
|
|
25
|
+
const stroke = mono ? ink : palette.ink;
|
|
26
|
+
const join = maker.lettering.corner === "round" ? "round" : "miter";
|
|
27
|
+
const letters = `<path fill="none" stroke="${stroke}" stroke-width="${r2(maker.lettering.weight)}" stroke-linecap="${maker.lettering.cap}" stroke-linejoin="${join}" d="${word.d}"/>`;
|
|
28
|
+
if (layout === "mark")
|
|
29
|
+
return { width: MARK, height: MARK, body: mark };
|
|
30
|
+
if (layout === "wordmark")
|
|
31
|
+
return { width: r2(word.width), height: r2(word.height), body: letters };
|
|
32
|
+
if (layout === "horizontal") {
|
|
33
|
+
const k = WORD_HEIGHT_BESIDE / LETTER_HEIGHT;
|
|
34
|
+
const top = MARK / 2 - (word.height * k) / 2;
|
|
35
|
+
return { width: r2(MARK + HORIZONTAL_GAP + word.width * k), height: MARK, body: `${mark}<g transform="translate(${MARK + HORIZONTAL_GAP} ${r2(top)}) scale(${r4(k)})">${letters}</g>` };
|
|
36
|
+
}
|
|
37
|
+
const k = Math.min(0.32, 96 / word.width);
|
|
38
|
+
const width = Math.max(MARK, word.width * k);
|
|
39
|
+
const x = (width - MARK) / 2;
|
|
40
|
+
const wx = (width - word.width * k) / 2;
|
|
41
|
+
return {
|
|
42
|
+
width: r2(width),
|
|
43
|
+
height: r2(MARK + STACK_GAP + word.height * k),
|
|
44
|
+
body: `<g transform="translate(${r2(x)} 0)">${mark}</g><g transform="translate(${r2(wx)} ${MARK + STACK_GAP}) scale(${r4(k)})">${letters}</g>`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function teamBody(team, o) {
|
|
48
|
+
const mono = o?.color === "mono";
|
|
49
|
+
const palette = o?.theme === "dark" ? team.dark : team.light;
|
|
50
|
+
const ink = monoInk(o?.ink);
|
|
51
|
+
return { width: MARK, height: MARK, body: partsMarkup(team.parts, (part) => (mono ? ink : palette[part.role])) };
|
|
52
|
+
}
|
|
53
|
+
function document(built, name, o) {
|
|
54
|
+
const height = clampSize(o?.size, 64);
|
|
55
|
+
const width = r2((height * built.width) / built.height);
|
|
56
|
+
const title = o?.title === false ? undefined : typeof o?.title === "string" ? o.title : name;
|
|
57
|
+
const label = title === undefined ? ' aria-hidden="true"' : ` role="img"`;
|
|
58
|
+
return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${built.width} ${built.height}" width="${width}" height="${r2(height)}"${label}>${title === undefined ? "" : `<title>${escape(title)}</title>`}${built.body}</svg>`;
|
|
59
|
+
}
|
|
60
|
+
function group(built, place) {
|
|
61
|
+
const size = clampSize(place?.size, MARK);
|
|
62
|
+
const k = size / built.height;
|
|
63
|
+
const x = typeof place?.x === "number" && Number.isFinite(place.x) ? place.x : 0;
|
|
64
|
+
const y = typeof place?.y === "number" && Number.isFinite(place.y) ? place.y : 0;
|
|
65
|
+
return `<g transform="translate(${r2(x)} ${r2(y)}) scale(${r4(k)})">${built.body}</g>`;
|
|
66
|
+
}
|
|
67
|
+
const layoutOf = (value) => (value === "wordmark" || value === "horizontal" || value === "stacked" ? value : "mark");
|
|
68
|
+
function maker(id) {
|
|
69
|
+
if (!Object.hasOwn(MAKERS, id))
|
|
70
|
+
throw new Error(`Unknown maker "${String(id).slice(0, 40)}"; see MAKER_IDS.`);
|
|
71
|
+
return MAKERS[id];
|
|
72
|
+
}
|
|
73
|
+
function team(id) {
|
|
74
|
+
if (!Object.hasOwn(TEAMS, id))
|
|
75
|
+
throw new Error(`Unknown team "${String(id).slice(0, 40)}"; see TEAM_IDS.`);
|
|
76
|
+
return TEAMS[id];
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* A fictional maker's logo as an SVG document: its mark by default, or its wordmark, or both (`layout`). In its own colours for a light or a dark page, or in one colour (`color: "mono"`, `ink`).
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* import { makerLogo } from "@johnmorrisdotca/dougu-sports/brands";
|
|
83
|
+
* const svg = makerLogo("arvane", { size: 48 });
|
|
84
|
+
* console.log(svg.startsWith("<svg"), svg.includes("<title>Arvane</title>"));
|
|
85
|
+
* // true true
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
export function makerLogo(id, o) {
|
|
89
|
+
const data = maker(id);
|
|
90
|
+
return document(makerBody(data, layoutOf(o?.layout), o), data.name, o);
|
|
91
|
+
}
|
|
92
|
+
/** A fictional team's logo as an SVG document, in its own colours for a light or a dark page, or in one colour. */
|
|
93
|
+
export function teamLogo(id, o) {
|
|
94
|
+
const data = team(id);
|
|
95
|
+
return document(teamBody(data, o), `${data.city} ${data.nickname}`, o);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* A maker's logo as a `<g>` to put inside another SVG: a jersey, a cap, a T-shirt, a card. It has no id, no gradient and no `<title>`, so any number of them can sit in one document. `x`, `y` and `size` place it in that drawing's units.
|
|
99
|
+
*/
|
|
100
|
+
export function makerLogoGroup(id, place, o) {
|
|
101
|
+
return group(makerBody(maker(id), layoutOf(o?.layout), o), place);
|
|
102
|
+
}
|
|
103
|
+
/** A team's logo as a `<g>` to put inside another SVG (see `makerLogoGroup`). */
|
|
104
|
+
export function teamLogoGroup(id, place, o) {
|
|
105
|
+
return group(teamBody(team(id), o), place);
|
|
106
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { MAKERS, MAKER_IDS, TEAMS, TEAM_IDS } from "./brands/brand.data.ts";
|
|
2
|
+
export type { LogoPart, MakerData, MakerId, MakerPalette, PartRole, TeamData, TeamId, TeamPalette } from "./brands/brand.data.ts";
|
|
3
|
+
export { makerLogo, makerLogoGroup, teamLogo, teamLogoGroup } from "./brands/brand.render.ts";
|
|
4
|
+
export type { LogoLayout, LogoOptions, LogoPlace, MakerLogoOptions } from "./brands/brand.render.ts";
|
|
5
|
+
export { makerBall, renderMakerBall } from "./brands/brand.ball.ts";
|
|
6
|
+
export type { MakerBallOptions } from "./brands/brand.ball.ts";
|
|
7
|
+
export { LETTERS, lettering } from "./brands/brand.letters.ts";
|
|
8
|
+
export type { LetterStyle, Lettering } from "./brands/brand.letters.ts";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// The brands entry point: twelve fictional maker marks, ten fictional team logos, and the functions that draw them, place them in another drawing or print them on a ball. The set is the data in `MAKERS` and `TEAMS`.
|
|
2
|
+
export { MAKERS, MAKER_IDS, TEAMS, TEAM_IDS } from "./brands/brand.data.js";
|
|
3
|
+
export { makerLogo, makerLogoGroup, teamLogo, teamLogoGroup } from "./brands/brand.render.js";
|
|
4
|
+
export { makerBall, renderMakerBall } from "./brands/brand.ball.js";
|
|
5
|
+
export { LETTERS, lettering } from "./brands/brand.letters.js";
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// Ribbon: a banner ribbon, a gold band with two red notched tails hanging behind it, drawn for this package, in metal, line and flat colour. It stands alone (a prize ribbon without a rosette); `trophy:rosette` is the one with ribbons.
|
|
2
|
+
import { defineFlat } from "../emblem.shapes.js";
|
|
3
|
+
/** Ribbon. */
|
|
4
|
+
export const AWARD_RIBBON = /* @__PURE__ */ defineFlat("award:ribbon", "Ribbon", "リボン", "ours", {
|
|
5
|
+
metal: "gold",
|
|
6
|
+
ribbon: "#c0392b",
|
|
7
|
+
front: [
|
|
8
|
+
// The two tails hang from behind the band, each ending in a notch.
|
|
9
|
+
["r", "M13 34H29V57L21 49L13 57z"],
|
|
10
|
+
["r", "M35 34H51V57L43 49L35 57z"],
|
|
11
|
+
// The band.
|
|
12
|
+
["m", "M5 10H59V34H5z"],
|
|
13
|
+
["e", "M9 14H55V30H9z", "1.6"],
|
|
14
|
+
["l", "M5 10H59V14H5z"],
|
|
15
|
+
],
|
|
16
|
+
rim: 2,
|
|
17
|
+
});
|
|
@@ -16,10 +16,10 @@ const TABLE = {
|
|
|
16
16
|
padel: ["ball:padel", ["gear:padel-racket"], "trophy:cup"],
|
|
17
17
|
squash: ["ball:squash", ["gear:squash-racket"], "trophy:cup", GOLD],
|
|
18
18
|
racquetball: ["ball:racquetball", ["gear:racquetball-racket"], "trophy:cup"],
|
|
19
|
-
sepaktakraw: ["ball:sepak-takraw", [], "trophy:cup"],
|
|
20
|
-
teqball: ["ball:teqball", [], "trophy:cup"],
|
|
19
|
+
sepaktakraw: ["ball:sepak-takraw", ["gear:takraw-net"], "trophy:cup"],
|
|
20
|
+
teqball: ["ball:teqball", ["gear:teqball-table"], "trophy:cup"],
|
|
21
21
|
roundnet: ["ball:roundnet", ["gear:roundnet-set"], "trophy:cup"],
|
|
22
|
-
netball: ["ball:netball", [], "trophy:cup"],
|
|
22
|
+
netball: ["ball:netball", ["gear:netball-post"], "trophy:cup"],
|
|
23
23
|
swimming: [undefined, ["gear:swim-goggles"], "trophy:cup", GOLD],
|
|
24
24
|
waterpolo: ["ball:water-polo", ["gear:swim-goggles"], "trophy:cup", GOLD],
|
|
25
25
|
diving: [undefined, ["gear:diving-board"], "trophy:cup", GOLD],
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
export declare const SPORT_NAMES: readonly ["nfl", "cfl", "ifaf", "nhl", "nba", "mlb", "soccer", "curling", "tennis", "volleyball", "badminton", "pickleball", "tabletennis", "padel", "squash", "racquetball", "sepaktakraw", "teqball", "roundnet", "netball", "swimming", "waterpolo", "diving", "artisticswimming", "lacrosse", "rugby", "afl", "gaelic", "cricket", "fieldhockey", "handball", "athletics", "skating", "sumo", "kendo", "judo", "kyudo", "karate"];
|
|
3
3
|
export type SportName = (typeof SPORT_NAMES)[number];
|
|
4
4
|
/** The awards: a medal on a ribbon, a badge, a crown, a star and a shield. */
|
|
5
|
-
export declare const AWARD_IDS: readonly ["award:medal", "award:badge", "award:crown", "award:star", "award:shield"];
|
|
5
|
+
export declare const AWARD_IDS: readonly ["award:medal", "award:badge", "award:crown", "award:star", "award:shield", "award:ribbon"];
|
|
6
6
|
export type AwardId = (typeof AWARD_IDS)[number];
|
|
7
7
|
/** The trophies: a cup for each league's champion in a descriptive, generic form, the plain cups and dishes, and the flat plaque, belt, wreath and rosette. */
|
|
8
8
|
export declare const TROPHY_IDS: 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"];
|
|
@@ -24,7 +24,7 @@ export type BallId = (typeof BALL_IDS)[number];
|
|
|
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"];
|
|
25
25
|
export type PuckId = (typeof PUCK_IDS)[number];
|
|
26
26
|
/** The pieces of gear: a piece of equipment for each sport, flat, drawn for this package, turning like a coin. */
|
|
27
|
-
export declare const GEAR_IDS: 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: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"];
|
|
27
|
+
export declare const GEAR_IDS: 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"];
|
|
28
28
|
export type GearId = (typeof GEAR_IDS)[number];
|
|
29
29
|
/** The Japanese sports and budo: sumo, kendo, judo, kyudo and karate, with the trophies and the gear that belong to them. Every one is also in its own group; this list is for showing them together. */
|
|
30
30
|
export declare const JAPANESE_IDS: readonly ["sport:sumo", "trophy:sumo-cup", "gear:gunbai", "gear:mawashi", "trophy:championship-banner", "sport:kendo", "gear:shinai", "gear:kendo-men", "sport:judo", "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", "sport:kyudo", "gear:yumi", "gear:ya", "sport:karate", "gear:karate-gi"];
|
|
@@ -39,13 +39,13 @@ export declare const SPORT_IDS: readonly SportEmblemId[];
|
|
|
39
39
|
export type EmblemId = AwardId | TrophyId | MedalId | CrestId | BallId | PuckId | GearId | SportEmblemId | PennantId;
|
|
40
40
|
/** The groups of ids, in the order a gallery shows them. */
|
|
41
41
|
export declare const EMBLEM_GROUPS: {
|
|
42
|
-
readonly award: readonly ["award:medal", "award:badge", "award:crown", "award:star", "award:shield"];
|
|
42
|
+
readonly award: readonly ["award:medal", "award:badge", "award:crown", "award:star", "award:shield", "award:ribbon"];
|
|
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"];
|
|
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
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-1970-black-white", "ball:soccer-1978-triad", "ball:soccer-1986-decorated-triad", "ball:soccer-1998-coloured-triad", "ball:soccer-2002-triangle-sweep", "ball:soccer-2006-propeller", "ball:soccer-2010-grooved", "ball:soccer-2014-ribbon", "ball:soccer-2018-pixel", "ball:soccer-2022-speed-shell", "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"];
|
|
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
|
-
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: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"];
|
|
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")[];
|
|
50
50
|
readonly pennant: readonly ["pennant:championship"];
|
|
51
51
|
};
|
|
@@ -7,7 +7,7 @@ export const SPORT_NAMES = [
|
|
|
7
7
|
"sumo", "kendo", "judo", "kyudo", "karate",
|
|
8
8
|
];
|
|
9
9
|
/** The awards: a medal on a ribbon, a badge, a crown, a star and a shield. */
|
|
10
|
-
export const AWARD_IDS = ["award:medal", "award:badge", "award:crown", "award:star", "award:shield"];
|
|
10
|
+
export const AWARD_IDS = ["award:medal", "award:badge", "award:crown", "award:star", "award:shield", "award:ribbon"];
|
|
11
11
|
/** The trophies: a cup for each league's champion in a descriptive, generic form, the plain cups and dishes, and the flat plaque, belt, wreath and rosette. */
|
|
12
12
|
export const TROPHY_IDS = [
|
|
13
13
|
"trophy:cup", "trophy:lidded-cup", "trophy:bowl", "trophy:salver", "trophy:globe",
|
|
@@ -37,7 +37,7 @@ export const PUCK_IDS = ["puck:canada", "puck:canada-red", "puck:canada-white",
|
|
|
37
37
|
export const GEAR_IDS = [
|
|
38
38
|
"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",
|
|
39
39
|
"gear:table-tennis-paddle", "gear:badminton-racket", "gear:tennis-racket", "gear:squash-racket", "gear:racquetball-racket", "gear:padel-racket", "gear:pickleball-paddle",
|
|
40
|
-
"gear:roundnet-set", "gear:volleyball-net", "gear:basketball-hoop", "gear:baseball-bat", "gear:baseball-glove", "gear:football-helmet", "gear:goalposts", "gear:hurley",
|
|
40
|
+
"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",
|
|
41
41
|
"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",
|
|
42
42
|
"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",
|
|
43
43
|
"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",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AWARD_MEDAL } from "./award/medal.js";
|
|
2
2
|
import { AWARD_BADGE } from "./award/badge.js";
|
|
3
3
|
import { AWARD_CROWN } from "./award/crown.js";
|
|
4
|
+
import { AWARD_RIBBON } from "./award/ribbon.js";
|
|
4
5
|
import { AWARD_STAR } from "./award/star.js";
|
|
5
6
|
import { AWARD_SHIELD } from "./award/shield.js";
|
|
6
7
|
import { TROPHY_CUP } from "./trophy/cup.js";
|
|
@@ -87,6 +88,7 @@ const OWN = {
|
|
|
87
88
|
"award:crown": AWARD_CROWN,
|
|
88
89
|
"award:star": AWARD_STAR,
|
|
89
90
|
"award:shield": AWARD_SHIELD,
|
|
91
|
+
"award:ribbon": AWARD_RIBBON,
|
|
90
92
|
"trophy:cup": TROPHY_CUP,
|
|
91
93
|
"trophy:lidded-cup": TROPHY_LIDDED_CUP,
|
|
92
94
|
"trophy:bowl": TROPHY_BOWL,
|
|
@@ -2,6 +2,7 @@ import { GEAR_BADMINTON_RACKET } from "./gear.badmintonracket.js";
|
|
|
2
2
|
import { GEAR_BASEBALL_GLOVE } from "./gear.baseballglove.js";
|
|
3
3
|
import { GEAR_CRICKET_BAT } from "./gear.cricketbat.js";
|
|
4
4
|
import { GEAR_BASEBALL_BAT, GEAR_BASKETBALL_HOOP, GEAR_VOLLEYBALL_NET, GEAR_GOALPOSTS, GEAR_WICKET, GEAR_ROUNDNET_SET } from "./gear.field.js";
|
|
5
|
+
import { GEAR_TAKRAW_NET, GEAR_NETBALL_POST, GEAR_TEQBALL_TABLE } from "./gear.nets.js";
|
|
5
6
|
import { GEAR_FIELD_HOCKEY_STICK } from "./gear.fieldhockeystick.js";
|
|
6
7
|
import { GEAR_FOOTBALL_HELMET } from "./gear.footballhelmet.js";
|
|
7
8
|
import { GEAR_GOALIE_MASK } from "./gear.goaliemask.js";
|
|
@@ -21,7 +22,7 @@ import { GEAR_JUDOGI, GEAR_JUDOGI_BLUE, GEAR_JUDOGI_FOLDED, GEAR_JUDOGI_BLUE_FOL
|
|
|
21
22
|
import { GEAR_OBI_STEP_1, GEAR_OBI_STEP_2, GEAR_OBI_STEP_3, GEAR_OBI_STEP_4, GEAR_OBI_STEP_5, GEAR_OBI_STEP_6 } from "./gear.budo.steps.js";
|
|
22
23
|
import { GEAR_YUMI, GEAR_YA } from "./gear.kyudo.js";
|
|
23
24
|
/** Every piece of gear, in the order a gallery shows them. */
|
|
24
|
-
export const GEARS = [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_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];
|
|
25
|
+
export const GEARS = [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];
|
|
25
26
|
/** The id of every piece of gear: `"gear:hockey-stick"`. */
|
|
26
27
|
export const GEAR_IDS = GEARS.map((g) => g.id);
|
|
27
28
|
const TABLE = new Map(GEARS.map((g) => [g.id, g]));
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare const GEAR_TAKRAW_NET: import("./gear.index.ts").Piece<import("./gear.core.ts").GearSpec>;
|
|
2
|
+
export declare const GEAR_NETBALL_POST: import("./gear.index.ts").Piece<import("./gear.core.ts").GearSpec>;
|
|
3
|
+
export declare const GEAR_TEQBALL_TABLE: import("./gear.index.ts").Piece<import("./gear.core.ts").GearSpec>;
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// The nets and posts of three sports, drawn for this package from their rulebooks' sizes: a sepak takraw net between its two posts, a netball goalpost with its ring and net, and a teqball table with its net.
|
|
2
|
+
// Each is drawn to the scale of its rule where the rule gives a size and the box allows; what is not to scale is said beside each drawing below and the sources are in NOTICE.md (a piece of gear claims no size of its own).
|
|
3
|
+
import { capsule, drawn, ellipse, rect, seg } from "./gear.core.js";
|
|
4
|
+
/** A number rounded for a path. */
|
|
5
|
+
const f = (n) => Math.round(n * 100) / 100;
|
|
6
|
+
// Not to scale: the net is drawn about 1.4 m long between its posts (the rule's minimum is 6.1 m) with a coarser mesh than 0.06-0.08 m, and the posts 0.08 m across (the rule's greatest radius is 0.04 m).
|
|
7
|
+
// Sepak takraw (ISTAF Law of the Game, Regu): the posts are 1.55 m for men, the net 0.70 m deep and at least 6.10 m long, its top 1.52 m at the centre and 1.55 m at the posts. 1.55 m is 52 units, so 1 m is 33.5.
|
|
8
|
+
const TAKRAW_M = 52 / 1.55;
|
|
9
|
+
const TAKRAW_FLOOR = 58.5;
|
|
10
|
+
const TAKRAW_TOP = TAKRAW_FLOOR - 52;
|
|
11
|
+
const TAKRAW_DEEP = 0.7 * TAKRAW_M;
|
|
12
|
+
const TAKRAW_SAG = 0.03 * TAKRAW_M;
|
|
13
|
+
const TAKRAW_LEFT = 9;
|
|
14
|
+
const TAKRAW_RIGHT = 55;
|
|
15
|
+
/** The y of the net's top edge across it: 1.55 m at the posts and 1.52 m at the centre (a parabola). */
|
|
16
|
+
const takrawTop = (x) => {
|
|
17
|
+
const u = (x - 32) / ((TAKRAW_RIGHT - TAKRAW_LEFT) / 2);
|
|
18
|
+
return TAKRAW_TOP + TAKRAW_SAG * (1 - u * u);
|
|
19
|
+
};
|
|
20
|
+
const takrawEdge = (dy) => `M${TAKRAW_LEFT} ${f(TAKRAW_TOP + dy)}Q32 ${f(TAKRAW_TOP + dy + 2 * TAKRAW_SAG)} ${TAKRAW_RIGHT} ${f(TAKRAW_TOP + dy)}`;
|
|
21
|
+
const TAKRAW_MESH = (() => {
|
|
22
|
+
let d = "";
|
|
23
|
+
for (let x = TAKRAW_LEFT + 3; x < TAKRAW_RIGHT - 1; x += 3)
|
|
24
|
+
d += seg(x, f(takrawTop(x) + 1), x, f(takrawTop(x) + TAKRAW_DEEP - 1));
|
|
25
|
+
for (let k = 1; k < 7; k++)
|
|
26
|
+
d += takrawEdge(1 + ((TAKRAW_DEEP - 2) * k) / 7);
|
|
27
|
+
return d;
|
|
28
|
+
})();
|
|
29
|
+
export const GEAR_TAKRAW_NET = /* @__PURE__ */ drawn("gear:takraw-net", "Sepak takraw net", "セパタクローのネット", {
|
|
30
|
+
main: "#f4f1ea",
|
|
31
|
+
accent: "#c8202c",
|
|
32
|
+
parts: [
|
|
33
|
+
{ d: seg(3, TAKRAW_FLOOR + 0.5, 61, TAKRAW_FLOOR + 0.5), stroke: "#8a949f", w: 1.2, line: "none" },
|
|
34
|
+
{ d: TAKRAW_MESH, stroke: "#4a5260", w: 0.6, line: "stroke" },
|
|
35
|
+
{ d: takrawEdge(0.9), stroke: "$main", w: 1.8 },
|
|
36
|
+
{ d: takrawEdge(TAKRAW_DEEP - 0.9), stroke: "$main", w: 1.8 },
|
|
37
|
+
{ d: rect(TAKRAW_LEFT, TAKRAW_TOP, 1.7, f(TAKRAW_DEEP), 0), fill: "$accent", shade: 0.3, line: "none" },
|
|
38
|
+
{ d: rect(TAKRAW_RIGHT - 1.7, TAKRAW_TOP, 1.7, f(TAKRAW_DEEP), 0), fill: "$accent", shade: 0.3, line: "none" },
|
|
39
|
+
{ d: capsule(TAKRAW_LEFT - 1.3, TAKRAW_FLOOR, TAKRAW_LEFT - 1.3, TAKRAW_TOP, 2.7), fill: "#9aa3ae", shade: 0.6, cyl: 0.8 },
|
|
40
|
+
{ d: capsule(TAKRAW_RIGHT + 1.3, TAKRAW_FLOOR, TAKRAW_RIGHT + 1.3, TAKRAW_TOP, 2.7), fill: "#9aa3ae", shade: 0.6, cyl: 0.8 },
|
|
41
|
+
],
|
|
42
|
+
});
|
|
43
|
+
// Not to scale: the pole is drawn 190 mm across (a padded middle pole), the ring's rod wider than 15 mm, the bar a little over 150 mm so that it reaches the ring, and the net 420 mm long (the rule: 380 to 457 mm).
|
|
44
|
+
// Netball (World Netball, Rules of Netball, 2024 edition, Rule 1 Technical specifications, 1.13 and 1.14 goalposts): a pole 3.05 m high and 65 to 100 mm across under padding up to 50 mm thick, a bar of 150 mm from the front edge at the top, a ring of 15 mm rod 380 mm inside, and a net 380 to 457 mm long.
|
|
45
|
+
// 3.05 m is 54 units, so 1 m is 17.7 units.
|
|
46
|
+
const NETBALL_M = 54 / 3.05;
|
|
47
|
+
const NETBALL_FLOOR = 59;
|
|
48
|
+
const NETBALL_TOP = NETBALL_FLOOR - 54;
|
|
49
|
+
const NETBALL_POLE = 25;
|
|
50
|
+
const NETBALL_BAR = 0.15 * NETBALL_M;
|
|
51
|
+
const NETBALL_RING_R = (0.38 / 2) * NETBALL_M;
|
|
52
|
+
const NETBALL_NET = 0.42 * NETBALL_M;
|
|
53
|
+
const ringX = NETBALL_POLE + 1.7 + NETBALL_BAR + NETBALL_RING_R;
|
|
54
|
+
const ringTilt = NETBALL_RING_R * 0.34;
|
|
55
|
+
const NETBALL_MESH = (() => {
|
|
56
|
+
let d = "";
|
|
57
|
+
for (let k = -3; k <= 3; k++) {
|
|
58
|
+
const x1 = ringX + (NETBALL_RING_R * k) / 3.4;
|
|
59
|
+
d += `M${f(x1)} ${f(NETBALL_TOP + 1.5 + ringTilt * Math.sqrt(Math.max(0, 1 - (k / 3.4) ** 2)))}L${f(x1 * 0.97 + ringX * 0.03)} ${f(NETBALL_TOP + 1.5 + NETBALL_NET)}`;
|
|
60
|
+
}
|
|
61
|
+
for (let r = 1; r < 4; r++)
|
|
62
|
+
d += `M${f(ringX - NETBALL_RING_R)} ${f(NETBALL_TOP + 1.5 + (NETBALL_NET * r) / 4)}H${f(ringX + NETBALL_RING_R)}`;
|
|
63
|
+
return d;
|
|
64
|
+
})();
|
|
65
|
+
export const GEAR_NETBALL_POST = /* @__PURE__ */ drawn("gear:netball-post", "Netball goalpost", "ネットボールのポスト", {
|
|
66
|
+
main: "#2b6cb5",
|
|
67
|
+
accent: "#d9dde2",
|
|
68
|
+
parts: [
|
|
69
|
+
{ d: seg(8, NETBALL_FLOOR + 0.5, 56, NETBALL_FLOOR + 0.5), stroke: "#8a949f", w: 1.2, line: "none" },
|
|
70
|
+
{ d: rect(NETBALL_POLE - 1.7, NETBALL_TOP, 3.4, NETBALL_FLOOR - NETBALL_TOP, 1.2), fill: "$main", shade: 0.5, cyl: 0.7 },
|
|
71
|
+
{ d: NETBALL_MESH, stroke: "#8f98a3", w: 0.5, line: "stroke" },
|
|
72
|
+
{ d: seg(NETBALL_POLE + 1.7, NETBALL_TOP + 1, NETBALL_POLE + 1.7 + NETBALL_BAR + 0.5, NETBALL_TOP + 1.5), stroke: "#8f98a3", w: 1.1 },
|
|
73
|
+
{ d: ellipse(f(ringX), NETBALL_TOP + 1.5, f(NETBALL_RING_R), f(ringTilt)), stroke: "$accent", w: 1.1, op: 0.95 },
|
|
74
|
+
],
|
|
75
|
+
});
|
|
76
|
+
// Not to scale: the table is seen from the side, so its width is not shown and the net's 20 mm thickness is a line; the legs' places and the surface's thickness are drawn by eye (the rules give none). The length, the heights and the net's 140 mm are to scale.
|
|
77
|
+
// Teqball (FITEQ, The Official Rules and Regulations of Teqball, 2025 edition effective 5 February 2025, 1.1.1-1.1.5 the table and 1.2.1-1.2.3 the net): 3,000 mm long, 900 mm to the top of the net; the playing surface 760 mm from the ground at its highest and 565 mm at its lowest; the net 140 mm above the surface.
|
|
78
|
+
// 3,000 mm is 54 units, so 1 m is 18.
|
|
79
|
+
const TEQ_S = 54 / 3000;
|
|
80
|
+
const TEQ_FLOOR = 42;
|
|
81
|
+
const TEQ_X0 = 5;
|
|
82
|
+
const TEQ_X1 = TEQ_X0 + 3000 * TEQ_S;
|
|
83
|
+
const TEQ_MID = (TEQ_X0 + TEQ_X1) / 2;
|
|
84
|
+
const TEQ_LOW = TEQ_FLOOR - 565 * TEQ_S;
|
|
85
|
+
const TEQ_HIGH = TEQ_FLOOR - 760 * TEQ_S;
|
|
86
|
+
const TEQ_NET_TOP = TEQ_FLOOR - 900 * TEQ_S;
|
|
87
|
+
/** The control point that puts the middle of a quadratic from the low end to the low end at the highest point. */
|
|
88
|
+
const TEQ_CTRL = 2 * TEQ_HIGH - TEQ_LOW;
|
|
89
|
+
/** The surface's thickness, drawn by eye. */
|
|
90
|
+
const TEQ_THICK = 2.4;
|
|
91
|
+
/** The surface's height at a distance t (0 to 1) along its length. */
|
|
92
|
+
const teqAt = (t) => (1 - t) * (1 - t) * TEQ_LOW + 2 * t * (1 - t) * TEQ_CTRL + t * t * TEQ_LOW;
|
|
93
|
+
const teqLeg = (t) => `M${f(TEQ_X0 + 3000 * TEQ_S * t)} ${f(TEQ_FLOOR)}V${f(teqAt(t) + TEQ_THICK - 0.4)}`;
|
|
94
|
+
export const GEAR_TEQBALL_TABLE = /* @__PURE__ */ drawn("gear:teqball-table", "Teqball table", "テックボールのテーブル", {
|
|
95
|
+
main: "#3f7fb5",
|
|
96
|
+
accent: "#e9eef2",
|
|
97
|
+
parts: [
|
|
98
|
+
{ d: seg(3, TEQ_FLOOR + 0.5, 61, TEQ_FLOOR + 0.5), stroke: "#8a949f", w: 1.2, line: "none" },
|
|
99
|
+
{ d: `${teqLeg(0.16)}${teqLeg(0.84)}`, stroke: "#6b7580", w: 2.4, line: "stroke" },
|
|
100
|
+
{ d: `M${f(TEQ_X0)} ${f(TEQ_LOW)}Q${f(TEQ_MID)} ${f(TEQ_CTRL)} ${f(TEQ_X1)} ${f(TEQ_LOW)}V${f(TEQ_LOW + TEQ_THICK)}Q${f(TEQ_MID)} ${f(TEQ_CTRL + TEQ_THICK)} ${f(TEQ_X0)} ${f(TEQ_LOW + TEQ_THICK)}z`, fill: "$main", shade: 0.7 },
|
|
101
|
+
{ d: rect(TEQ_MID - 0.6, TEQ_NET_TOP, 1.2, TEQ_HIGH - TEQ_NET_TOP + 0.4, 0.2), fill: "$accent", shade: 0.2 },
|
|
102
|
+
],
|
|
103
|
+
});
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { EMBLEM_TABLE } from "./emblems/emblem.registry.ts";
|
|
|
6
6
|
export { AWARD_MEDAL } from "./emblems/award/medal.ts";
|
|
7
7
|
export { AWARD_BADGE } from "./emblems/award/badge.ts";
|
|
8
8
|
export { AWARD_CROWN } from "./emblems/award/crown.ts";
|
|
9
|
+
export { AWARD_RIBBON } from "./emblems/award/ribbon.ts";
|
|
9
10
|
export { AWARD_STAR } from "./emblems/award/star.ts";
|
|
10
11
|
export { AWARD_SHIELD } from "./emblems/award/shield.ts";
|
|
11
12
|
export { TROPHY_CUP } from "./emblems/trophy/cup.ts";
|
|
@@ -123,6 +124,7 @@ export { GEAR_BADMINTON_RACKET } from "./emblems/gear/gear.badmintonracket.ts";
|
|
|
123
124
|
export { GEAR_BASEBALL_GLOVE } from "./emblems/gear/gear.baseballglove.ts";
|
|
124
125
|
export { GEAR_CRICKET_BAT } from "./emblems/gear/gear.cricketbat.ts";
|
|
125
126
|
export { GEAR_BASEBALL_BAT, GEAR_BASKETBALL_HOOP, GEAR_VOLLEYBALL_NET, GEAR_GOALPOSTS, GEAR_WICKET, GEAR_ROUNDNET_SET } from "./emblems/gear/gear.field.ts";
|
|
127
|
+
export { GEAR_TAKRAW_NET, GEAR_NETBALL_POST, GEAR_TEQBALL_TABLE } from "./emblems/gear/gear.nets.ts";
|
|
126
128
|
export { GEAR_FIELD_HOCKEY_STICK } from "./emblems/gear/gear.fieldhockeystick.ts";
|
|
127
129
|
export { GEAR_FOOTBALL_HELMET } from "./emblems/gear/gear.footballhelmet.ts";
|
|
128
130
|
export { GEAR_GOALIE_MASK } from "./emblems/gear/gear.goaliemask.ts";
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export { EMBLEM_TABLE } from "./emblems/emblem.registry.js";
|
|
|
7
7
|
export { AWARD_MEDAL } from "./emblems/award/medal.js";
|
|
8
8
|
export { AWARD_BADGE } from "./emblems/award/badge.js";
|
|
9
9
|
export { AWARD_CROWN } from "./emblems/award/crown.js";
|
|
10
|
+
export { AWARD_RIBBON } from "./emblems/award/ribbon.js";
|
|
10
11
|
export { AWARD_STAR } from "./emblems/award/star.js";
|
|
11
12
|
export { AWARD_SHIELD } from "./emblems/award/shield.js";
|
|
12
13
|
export { TROPHY_CUP } from "./emblems/trophy/cup.js";
|
|
@@ -123,6 +124,7 @@ export { GEAR_BADMINTON_RACKET } from "./emblems/gear/gear.badmintonracket.js";
|
|
|
123
124
|
export { GEAR_BASEBALL_GLOVE } from "./emblems/gear/gear.baseballglove.js";
|
|
124
125
|
export { GEAR_CRICKET_BAT } from "./emblems/gear/gear.cricketbat.js";
|
|
125
126
|
export { GEAR_BASEBALL_BAT, GEAR_BASKETBALL_HOOP, GEAR_VOLLEYBALL_NET, GEAR_GOALPOSTS, GEAR_WICKET, GEAR_ROUNDNET_SET } from "./emblems/gear/gear.field.js";
|
|
127
|
+
export { GEAR_TAKRAW_NET, GEAR_NETBALL_POST, GEAR_TEQBALL_TABLE } from "./emblems/gear/gear.nets.js";
|
|
126
128
|
export { GEAR_FIELD_HOCKEY_STICK } from "./emblems/gear/gear.fieldhockeystick.js";
|
|
127
129
|
export { GEAR_FOOTBALL_HELMET } from "./emblems/gear/gear.footballhelmet.js";
|
|
128
130
|
export { GEAR_GOALIE_MASK } from "./emblems/gear/gear.goaliemask.js";
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.10.0";
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = "0.
|
|
1
|
+
export const VERSION = "0.10.0";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@johnmorrisdotca/dougu-sports",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.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",
|
|
@@ -53,6 +53,11 @@
|
|
|
53
53
|
"import": "./dist/emblems-entry.js",
|
|
54
54
|
"default": "./dist/emblems-entry.js"
|
|
55
55
|
},
|
|
56
|
+
"./brands": {
|
|
57
|
+
"types": "./dist/brands-entry.d.ts",
|
|
58
|
+
"import": "./dist/brands-entry.js",
|
|
59
|
+
"default": "./dist/brands-entry.js"
|
|
60
|
+
},
|
|
56
61
|
"./turn": {
|
|
57
62
|
"types": "./dist/turn-entry.d.ts",
|
|
58
63
|
"import": "./dist/turn-entry.js",
|
|
@@ -122,12 +127,14 @@
|
|
|
122
127
|
"family:readme": "node scripts/family-readme.mjs",
|
|
123
128
|
"dev": "pnpm build && node scripts/dev.ts",
|
|
124
129
|
"gallery": "pnpm build && node scripts/make-gallery.ts",
|
|
130
|
+
"flags": "node scripts/make-flags.mjs",
|
|
125
131
|
"site": "pnpm build && node scripts/site.ts",
|
|
126
132
|
"test:demo": "pnpm site && playwright test",
|
|
127
133
|
"screenshots": "pnpm site && node scripts/screenshots.ts"
|
|
128
134
|
},
|
|
129
135
|
"devDependencies": {
|
|
130
136
|
"@eslint/js": "^9.0.0",
|
|
137
|
+
"@johnmorrisdotca/hata": "1.5.0",
|
|
131
138
|
"@playwright/test": "^1.63.0",
|
|
132
139
|
"@types/node": "^24.0.0",
|
|
133
140
|
"esbuild": "^0.25.0",
|