@chocbite/ts-lib-svg 1.1.0 → 1.1.1
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/README.md +231 -0
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# @chocbite/ts-lib-svg
|
|
2
|
+
|
|
3
|
+
A TypeScript library for programmatic SVG generation with a fluent, chainable API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @chocbite/ts-lib-svg
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { svg } from "@chocbite/ts-lib-svg";
|
|
15
|
+
|
|
16
|
+
// Create an SVG canvas and append a red circle
|
|
17
|
+
const canvas = svg.svg(200, 200).elem;
|
|
18
|
+
canvas.appendChild(
|
|
19
|
+
svg.circle(100, 100, 40).fill("red").stroke("black").stroke_width(2).elem
|
|
20
|
+
);
|
|
21
|
+
document.body.appendChild(canvas);
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## API
|
|
25
|
+
|
|
26
|
+
All drawing functions return an `SVGAttributes` wrapper that supports chaining. Call `.elem` to get the underlying `SVGElement`.
|
|
27
|
+
|
|
28
|
+
### Primitives
|
|
29
|
+
|
|
30
|
+
#### `svg.svg(width, height, viewbox?)`
|
|
31
|
+
|
|
32
|
+
Creates an `<svg>` root element. The viewbox defaults to `"0 0 <width> <height>"`.
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
const canvas = svg.svg(400, 300).elem;
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
#### `svg.circle(center_x, center_y, radius)`
|
|
39
|
+
|
|
40
|
+
Creates a `<circle>` element.
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
svg.circle(50, 50, 25).fill("blue").elem;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
#### `svg.ellipse(center_x, center_y, radius_x, radius_y)`
|
|
47
|
+
|
|
48
|
+
Creates an `<ellipse>` element.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
svg.ellipse(100, 100, 60, 30).fill("green").stroke("black").elem;
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
#### `svg.rectangle_from_center(center_x, center_y, width, height, corner_radius)`
|
|
55
|
+
|
|
56
|
+
Creates a `<rect>` positioned by its center point.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
svg.rectangle_from_center(100, 100, 80, 40, 5).fill("orange").elem;
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
#### `svg.rectangle_from_corner(start_x, start_y, width, height, corner_radius)`
|
|
63
|
+
|
|
64
|
+
Creates a `<rect>` positioned by its top-left corner.
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
svg.rectangle_from_corner(10, 10, 80, 40, 0).fill("purple").elem;
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
#### `svg.line(start_x, start_y, end_x, end_y)`
|
|
71
|
+
|
|
72
|
+
Creates a `<line>` element.
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
svg.line(0, 0, 100, 100).stroke("black").stroke_width(2).elem;
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
#### `svg.path(d)`
|
|
79
|
+
|
|
80
|
+
Creates a `<path>` element with the given path data string.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
svg.path("M 10 80 C 40 10, 65 10, 95 80").stroke("black").fill("none").elem;
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
#### `svg.isosceles_triangle(center_x, center_y, width, height)`
|
|
87
|
+
|
|
88
|
+
Creates an isosceles triangle as a `<path>`.
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
svg.isosceles_triangle(100, 100, 60, 80).fill("yellow").stroke("black").elem;
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
#### `svg.circle_arc(center_x, center_y, radius, start_angle, end_angle)`
|
|
95
|
+
|
|
96
|
+
Draws a circular arc. Angles are in degrees.
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
svg.circle_arc(100, 100, 50, 0, 90).stroke("red").fill("none").stroke_width(2).elem;
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
#### `svg.ellipse_arc(center_x, center_y, radius_x, radius_y, start_angle, end_angle)`
|
|
103
|
+
|
|
104
|
+
Draws an elliptical arc. Angles are in degrees.
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
svg.ellipse_arc(100, 100, 60, 30, 0, 180).stroke("blue").fill("none").elem;
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
#### `svg.text(x, y, text, size, anchor)`
|
|
111
|
+
|
|
112
|
+
Creates a single-line `<text>` element. The `anchor` parameter controls text alignment using `SVGAnchorPoint`.
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import { svg, SVGAnchorPoint } from "@chocbite/ts-lib-svg";
|
|
116
|
+
|
|
117
|
+
svg.text(100, 50, "Hello", 16, SVGAnchorPoint.middleCenter).fill("black").elem;
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
#### `svg.multi_line_text(x, y, width, height, text, size, anchor)`
|
|
121
|
+
|
|
122
|
+
Creates a multi-line text block using a `<foreignObject>` with an inner `<div>`.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
svg.multi_line_text(10, 10, 200, 100, "Long text that wraps", 14, SVGAnchorPoint.topLeft).elem;
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
#### `svg.group()`
|
|
129
|
+
|
|
130
|
+
Creates a `<g>` group element. Append child elements to it.
|
|
131
|
+
|
|
132
|
+
```ts
|
|
133
|
+
const g = svg.group().translate(50, 50).elem;
|
|
134
|
+
g.appendChild(svg.circle(0, 0, 20).fill("red").elem);
|
|
135
|
+
g.appendChild(svg.circle(40, 0, 20).fill("blue").elem);
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
#### `svg.create(tagName)`
|
|
139
|
+
|
|
140
|
+
Creates an arbitrary SVG element by tag name (e.g. `"defs"`, `"clipPath"`).
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
const defs = svg.create("defs").elem;
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Chaining Attributes
|
|
147
|
+
|
|
148
|
+
Every primitive returns an `SVGAttributes` wrapper with chainable methods:
|
|
149
|
+
|
|
150
|
+
| Method | Shorthand | Description |
|
|
151
|
+
|---|---|---|
|
|
152
|
+
| `.fill(color)` | `.f(color)` | Set fill color |
|
|
153
|
+
| `.stroke(color)` | `.s(color)` | Set stroke color |
|
|
154
|
+
| `.stroke_width(n)` | `.sw(n)` | Set stroke width |
|
|
155
|
+
| `.class_list(...names)` | `.cl(...names)` | Add CSS class names |
|
|
156
|
+
| `.attribute(name, value)` | `.a(name, value)` | Set any attribute |
|
|
157
|
+
| `.translate(x, y)` | | Apply translate transform |
|
|
158
|
+
| `.rotate(angle, cx?, cy?)` | | Apply rotate transform |
|
|
159
|
+
| `.scale(sx, sy?)` | | Apply scale transform |
|
|
160
|
+
| `.skewX(angle)` | | Apply skewX transform |
|
|
161
|
+
| `.skewY(angle)` | | Apply skewY transform |
|
|
162
|
+
| `.transform(str)` | | Apply a custom transform string |
|
|
163
|
+
| `.elem` | | Get the underlying `SVGElement` |
|
|
164
|
+
|
|
165
|
+
Transforms are accumulated and written to the `transform` attribute when `.elem` is accessed.
|
|
166
|
+
|
|
167
|
+
```ts
|
|
168
|
+
svg.circle(0, 0, 10)
|
|
169
|
+
.fill("red")
|
|
170
|
+
.stroke("black")
|
|
171
|
+
.stroke_width(1)
|
|
172
|
+
.class_list("my-circle")
|
|
173
|
+
.translate(50, 50)
|
|
174
|
+
.rotate(45)
|
|
175
|
+
.elem;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Utilities
|
|
179
|
+
|
|
180
|
+
#### `SVGAnchorPoint`
|
|
181
|
+
|
|
182
|
+
An enum-like object describing text anchor positions:
|
|
183
|
+
|
|
184
|
+
```ts
|
|
185
|
+
import { SVGAnchorPoint } from "@chocbite/ts-lib-svg";
|
|
186
|
+
|
|
187
|
+
SVGAnchorPoint.topLeft; // 2
|
|
188
|
+
SVGAnchorPoint.topCenter; // 3
|
|
189
|
+
SVGAnchorPoint.topRight; // 4
|
|
190
|
+
SVGAnchorPoint.middleLeft; // 1
|
|
191
|
+
SVGAnchorPoint.middleCenter; // 8
|
|
192
|
+
SVGAnchorPoint.middleRight; // 5
|
|
193
|
+
SVGAnchorPoint.bottomLeft; // 0
|
|
194
|
+
SVGAnchorPoint.bottomCenter; // 7
|
|
195
|
+
SVGAnchorPoint.bottomRight; // 6
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### `svg.angle_to_anchor_point(angle)`
|
|
199
|
+
|
|
200
|
+
Converts an angle (in radians) to the nearest `SVGAnchorPoint`. Useful for placing labels around a circle.
|
|
201
|
+
|
|
202
|
+
```ts
|
|
203
|
+
const anchor = svg.angle_to_anchor_point(Math.PI / 4); // bottomRight
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Full Example
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
import { svg, SVGAnchorPoint } from "@chocbite/ts-lib-svg";
|
|
210
|
+
|
|
211
|
+
const canvas = svg.svg(300, 300).elem;
|
|
212
|
+
|
|
213
|
+
// Background
|
|
214
|
+
canvas.appendChild(
|
|
215
|
+
svg.rectangle_from_corner(0, 0, 300, 300, 0).fill("#f0f0f0").elem
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
// Grouped shapes
|
|
219
|
+
const g = svg.group().translate(150, 150).elem;
|
|
220
|
+
g.appendChild(svg.circle(0, 0, 50).fill("none").stroke("steelblue").stroke_width(2).elem);
|
|
221
|
+
g.appendChild(svg.line(-50, 0, 50, 0).stroke("gray").stroke_width(1).elem);
|
|
222
|
+
g.appendChild(svg.line(0, -50, 0, 50).stroke("gray").stroke_width(1).elem);
|
|
223
|
+
g.appendChild(svg.text(0, -60, "Center", 12, SVGAnchorPoint.bottomCenter).fill("black").elem);
|
|
224
|
+
canvas.appendChild(g);
|
|
225
|
+
|
|
226
|
+
document.body.appendChild(canvas);
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## License
|
|
230
|
+
|
|
231
|
+
MIT
|