figureone 1.0.1 → 1.0.3
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/figureone.min.js +1 -1
- package/index.js +16 -2
- package/llms-full.txt +2499 -0
- package/package.json +3 -2
- package/types/js/figure/webgl/webgl.d.ts +1 -1
package/llms-full.txt
ADDED
|
@@ -0,0 +1,2499 @@
|
|
|
1
|
+
# FigureOne - Complete API Reference
|
|
2
|
+
> For a quick overview, see llms.txt
|
|
3
|
+
|
|
4
|
+
FigureOne is a JavaScript library for drawing, animating, and interacting with shapes, text, plots, and equations in a browser using WebGL. `Fig` is the global entry point. `new Fig.Figure()` creates a figure attached to `<div id="figureOneContainer">`. Elements are added with `figure.add({ make: 'type', ...options })`.
|
|
5
|
+
|
|
6
|
+
Colors are `[r, g, b, a]` with values 0-1. Default scene is `[-1, -1, 2, 2]` (x, y, width, height).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. Figure Class
|
|
11
|
+
|
|
12
|
+
### OBJ_Figure
|
|
13
|
+
|
|
14
|
+
| Property | Type | Default | Description |
|
|
15
|
+
|---|---|---|---|
|
|
16
|
+
| htmlId | string | `'figureOneContainer'` | HTML div id to attach figure to |
|
|
17
|
+
| scene | OBJ_Scene \| [x,y,w,h] | `[-1, -1, 2, 2]` | Scene definition (2D rect or full scene object) |
|
|
18
|
+
| color | TypeColor | `[0, 0, 0, 1]` | Default shape color |
|
|
19
|
+
| font | OBJ_Font | `{family:'Times New Roman', size:0.2}` | Default font |
|
|
20
|
+
| lineWidth | number | | Default line width |
|
|
21
|
+
| length | number | | Default primary dimension |
|
|
22
|
+
| backgroundColor | TypeColor | | Background color |
|
|
23
|
+
|
|
24
|
+
### Key Figure Methods
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
const figure = new Fig.Figure({ htmlId: 'myDiv', scene: [-2, -2, 4, 4] });
|
|
28
|
+
|
|
29
|
+
// Add single element (returns the element)
|
|
30
|
+
const elem = figure.add({ make: 'polygon', sides: 6, radius: 0.5 });
|
|
31
|
+
|
|
32
|
+
// Add multiple elements (returns array)
|
|
33
|
+
const [a, b] = figure.add([
|
|
34
|
+
{ make: 'polygon', sides: 4, radius: 0.3, name: 'sq' },
|
|
35
|
+
{ make: 'polygon', sides: 100, radius: 0.2, name: 'circ' },
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
// Access elements
|
|
39
|
+
figure.elements._sq;
|
|
40
|
+
figure.getElement('sq');
|
|
41
|
+
|
|
42
|
+
// Control
|
|
43
|
+
figure.stop(); // Stop all animations
|
|
44
|
+
figure.resize(); // Resize after container change
|
|
45
|
+
figure.animateNextFrame(); // Request next animation frame
|
|
46
|
+
figure.isAnimating(); // Check if any animation running
|
|
47
|
+
|
|
48
|
+
// Coordinate transforms
|
|
49
|
+
figure.transformPoint(point, fromSpace, toSpace);
|
|
50
|
+
figure.spaceTransformMatrix(fromSpace, toSpace);
|
|
51
|
+
|
|
52
|
+
// SlideNavigator
|
|
53
|
+
const nav = figure.addSlideNavigator({ slides: [...] });
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## 2. Common Base Types
|
|
59
|
+
|
|
60
|
+
### TypeColor
|
|
61
|
+
`[r, g, b, a]` — array of 4 numbers, each 0-1. Example: `[1, 0, 0, 1]` = red.
|
|
62
|
+
|
|
63
|
+
### TypeParsablePoint
|
|
64
|
+
Any of: `[x, y]`, `[x, y, z]`, `new Fig.Point(x, y)`, or a Point instance.
|
|
65
|
+
|
|
66
|
+
### TypeParsableTransform
|
|
67
|
+
Any of: a Transform instance, or an array of transform components:
|
|
68
|
+
- Translation: `['t', x, y, z]`
|
|
69
|
+
- Rotation 2D: `['r', angle]`
|
|
70
|
+
- Rotation 3D: `['r', angle, axisX, axisY, axisZ]`
|
|
71
|
+
- Scale: `['s', sx, sy, sz]`
|
|
72
|
+
- Direction: `['d', dx, dy, dz]`
|
|
73
|
+
|
|
74
|
+
Example: `[['t', 0.5, 0], ['r', Math.PI/4], ['s', 2, 2]]`
|
|
75
|
+
|
|
76
|
+
### TypeElementPath
|
|
77
|
+
Path to figure element(s) within a collection. Supports multiple formats:
|
|
78
|
+
- String dot-path: `'parent.child.grandchild'`
|
|
79
|
+
- Direct reference: a FigureElement instance
|
|
80
|
+
- Object paths: `{ parent: ['child.a', 'child.b'] }`
|
|
81
|
+
- Array of any above: `['elem1', 'elem2', figureElement]`
|
|
82
|
+
|
|
83
|
+
### OBJ_Font
|
|
84
|
+
|
|
85
|
+
| Property | Type | Default | Description |
|
|
86
|
+
|---|---|---|---|
|
|
87
|
+
| family | string | `'Times New Roman'` | Font family |
|
|
88
|
+
| style | `'normal'` \| `'italic'` | `'normal'` | Font style |
|
|
89
|
+
| weight | string \| number | `'normal'` | Font weight |
|
|
90
|
+
| size | number | `0.2` | Size in draw space units |
|
|
91
|
+
| color | TypeColor \| null | | Font color |
|
|
92
|
+
| underline | boolean \| object | `false` | Underline options |
|
|
93
|
+
| outline | boolean \| object | `false` | Outline options |
|
|
94
|
+
| render | `'gl'` \| `'2d'` \| `'html'` | `'gl'` | Render target |
|
|
95
|
+
|
|
96
|
+
### OBJ_Texture
|
|
97
|
+
|
|
98
|
+
| Property | Type | Default | Description |
|
|
99
|
+
|---|---|---|---|
|
|
100
|
+
| src | string | | Image URL |
|
|
101
|
+
| coords | number[] | `[]` | Texture coordinates per vertex |
|
|
102
|
+
| mapFrom | [x,y,w,h] | `[0, 0, 1, 1]` | Image space window |
|
|
103
|
+
| mapTo | [x,y,w,h] | `[-1, -1, 2, 2]` | Draw space window |
|
|
104
|
+
| repeat | boolean | `false` | Tile image (power-of-2 only) |
|
|
105
|
+
| loadColor | TypeColor | `[0, 0, 1, 0.5]` | Color while loading |
|
|
106
|
+
| onLoad | () => void | | Callback after load |
|
|
107
|
+
|
|
108
|
+
### OBJ_FigurePrimitive (base for all primitives)
|
|
109
|
+
|
|
110
|
+
| Property | Type | Default | Description |
|
|
111
|
+
|---|---|---|---|
|
|
112
|
+
| name | string | | Element name |
|
|
113
|
+
| position | TypeParsablePoint | | Shorthand for translation |
|
|
114
|
+
| transform | TypeParsableTransform | | Full transform |
|
|
115
|
+
| color | TypeColor | | Element color |
|
|
116
|
+
| touch | boolean \| OBJ_Touch | `false` | Enable touch |
|
|
117
|
+
| move | boolean \| OBJ_ElementMove | `false` | Enable dragging |
|
|
118
|
+
| dimColor | TypeColor | | Color when dimmed |
|
|
119
|
+
| defaultColor | TypeColor | | Color when undimmed |
|
|
120
|
+
| scenarios | OBJ_Scenarios | | Named presets |
|
|
121
|
+
| scene | Scene \| OBJ_Scene | | Custom scene |
|
|
122
|
+
|
|
123
|
+
### OBJ_Collection
|
|
124
|
+
|
|
125
|
+
| Property | Type | Default | Description |
|
|
126
|
+
|---|---|---|---|
|
|
127
|
+
| transform | TypeParsableTransform | | Collection transform |
|
|
128
|
+
| position | TypeParsablePoint | | Overwrites transform translation |
|
|
129
|
+
| color | TypeColor | | Default color |
|
|
130
|
+
| parent | FigureElement \| null | | Parent element |
|
|
131
|
+
| border | string \| number | `'children'` | Border: `'children'`, `'rect'`, or number buffer |
|
|
132
|
+
| touchBorder | string \| number | `'children'` | Touch border |
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## 3. 2D Shape Primitives
|
|
137
|
+
|
|
138
|
+
All 2D primitives extend OBJ_FigurePrimitive. Properties from OBJ_FigurePrimitive (name, position, color, etc.) are always available.
|
|
139
|
+
|
|
140
|
+
### OBJ_Generic (`make: 'generic'`)
|
|
141
|
+
|
|
142
|
+
| Property | Type | Default | Description |
|
|
143
|
+
|---|---|---|---|
|
|
144
|
+
| points | TypeParsablePoint[] | | Vertex positions |
|
|
145
|
+
| drawType | `'TRIANGLES'` \| `'POINTS'` \| `'FAN'` \| `'STRIP'` \| `'LINES'` | `'TRIANGLES'` | GL primitive type |
|
|
146
|
+
| copy | CPY_Step[] \| CPY_Step | `[]` | Copy/repeat pattern |
|
|
147
|
+
| texture | OBJ_Texture | | Texture fill |
|
|
148
|
+
| drawBorder | TypeParsableBorder | | Shape border points |
|
|
149
|
+
| drawBorderBuffer | TypeParsableBorder | | Buffer border points |
|
|
150
|
+
| border | string \| number | `'draw'` | `'draw'`, `'buffer'`, `'rect'`, or number |
|
|
151
|
+
| touchBorder | string \| number | `'border'` | `'border'`, `'draw'`, `'buffer'`, `'rect'`, or number |
|
|
152
|
+
| pulse | number | | Default pulse scale |
|
|
153
|
+
|
|
154
|
+
### CPY_Step (copy pattern)
|
|
155
|
+
|
|
156
|
+
| Property | Type | Default | Description |
|
|
157
|
+
|---|---|---|---|
|
|
158
|
+
| along | `'x'` \| `'y'` \| `'z'` \| `'rotation'` | | Copy direction |
|
|
159
|
+
| num | number | | Number of copies |
|
|
160
|
+
| step | number | | Step distance or angle |
|
|
161
|
+
| to | TypeParsablePoint \| Transform | | Copy to position/transform |
|
|
162
|
+
| start | number | `0` | Start index |
|
|
163
|
+
| end | number | | End index |
|
|
164
|
+
| original | boolean | `true` | Include original |
|
|
165
|
+
|
|
166
|
+
### OBJ_Polyline (`make: 'polyline'`)
|
|
167
|
+
Extends OBJ_Generic (without drawType).
|
|
168
|
+
|
|
169
|
+
| Property | Type | Default | Description |
|
|
170
|
+
|---|---|---|---|
|
|
171
|
+
| points | TypeParsablePoint[] | | Corner points |
|
|
172
|
+
| width | number | `0.01` | Line width |
|
|
173
|
+
| close | boolean | `false` | Close polyline |
|
|
174
|
+
| simple | boolean | `false` | Simple mode (fast, fewer features) |
|
|
175
|
+
| widthIs | `'mid'` \| `'outside'` \| `'inside'` \| `'positive'` \| `'negative'` \| number | `'mid'` | Width growth direction |
|
|
176
|
+
| cornerStyle | `'auto'` \| `'none'` \| `'radius'` \| `'fill'` | `'auto'` | Corner rendering |
|
|
177
|
+
| cornerSize | number | `0.01` | Corner radius (when `'radius'`) |
|
|
178
|
+
| cornerSides | number | `10` | Sides in corner curve |
|
|
179
|
+
| cornersOnly | boolean | `false` | Draw only corners |
|
|
180
|
+
| cornerLength | number | `0.1` | Corner length when cornersOnly |
|
|
181
|
+
| minAutoCornerAngle | number | `π/7` | Threshold for auto corners |
|
|
182
|
+
| dash | number[] | | Dash pattern: `[lineLen, gapLen, ...]` |
|
|
183
|
+
| arrow | OBJ_LineArrows \| TypeArrowHead | | Arrow on ends |
|
|
184
|
+
| linePrimitives | boolean | `false` | Use GL line primitives |
|
|
185
|
+
|
|
186
|
+
### OBJ_Polygon (`make: 'polygon'`)
|
|
187
|
+
Extends OBJ_Generic (without drawType).
|
|
188
|
+
|
|
189
|
+
| Property | Type | Default | Description |
|
|
190
|
+
|---|---|---|---|
|
|
191
|
+
| sides | number | `4` | Number of sides |
|
|
192
|
+
| radius | number | `1` | Radius |
|
|
193
|
+
| rotation | number | `0` | Shape rotation (vertex definition) |
|
|
194
|
+
| offset | TypeParsablePoint | `[0, 0]` | Center offset |
|
|
195
|
+
| sidesToDraw | number | all | Number of sides to draw |
|
|
196
|
+
| angleToDraw | number | `2π` | Angle to draw |
|
|
197
|
+
| direction | `1` \| `-1` | `1` | 1=CCW, -1=CW |
|
|
198
|
+
| line | OBJ_LineStyleSimple | | Line style (outline mode) |
|
|
199
|
+
|
|
200
|
+
### OBJ_Star (`make: 'star'`)
|
|
201
|
+
Extends OBJ_Generic (without drawType).
|
|
202
|
+
|
|
203
|
+
| Property | Type | Default | Description |
|
|
204
|
+
|---|---|---|---|
|
|
205
|
+
| sides | number | `4` | Number of points |
|
|
206
|
+
| radius | number | `1` | Outer radius |
|
|
207
|
+
| innerRadius | number | `radius/2` | Inner radius |
|
|
208
|
+
| rotation | number | `0` | Shape rotation |
|
|
209
|
+
| offset | TypeParsablePoint | `[0, 0]` | Center offset |
|
|
210
|
+
| line | OBJ_LineStyleSimple | | Line style |
|
|
211
|
+
|
|
212
|
+
### OBJ_Rectangle (`make: 'rectangle'`)
|
|
213
|
+
Extends OBJ_Generic (without drawType).
|
|
214
|
+
|
|
215
|
+
| Property | Type | Default | Description |
|
|
216
|
+
|---|---|---|---|
|
|
217
|
+
| width | number | `1` | Width |
|
|
218
|
+
| height | number | `1` | Height |
|
|
219
|
+
| xAlign | `'left'` \| `'center'` \| `'right'` \| number | `'center'` | Horizontal alignment |
|
|
220
|
+
| yAlign | `'bottom'` \| `'middle'` \| `'top'` \| number | `'middle'` | Vertical alignment |
|
|
221
|
+
| corner | OBJ_CurvedCorner | | Rounded corners: `{ radius, sides }` |
|
|
222
|
+
| line | OBJ_LineStyleSimple | | Line style |
|
|
223
|
+
| offset | TypeParsablePoint | | Position offset |
|
|
224
|
+
|
|
225
|
+
### OBJ_Ellipse (`make: 'ellipse'`)
|
|
226
|
+
Extends OBJ_Generic (without drawType).
|
|
227
|
+
|
|
228
|
+
| Property | Type | Default | Description |
|
|
229
|
+
|---|---|---|---|
|
|
230
|
+
| width | number | `1` | Width |
|
|
231
|
+
| height | number | `1` | Height |
|
|
232
|
+
| xAlign | `'left'` \| `'center'` \| `'right'` \| number | `'center'` | Horizontal alignment |
|
|
233
|
+
| yAlign | `'bottom'` \| `'middle'` \| `'top'` \| number | `'middle'` | Vertical alignment |
|
|
234
|
+
| sides | number | `20` | Number of sides |
|
|
235
|
+
| line | OBJ_LineStyleSimple | | Line style |
|
|
236
|
+
|
|
237
|
+
### OBJ_Arc (`make: 'arc'`)
|
|
238
|
+
Extends OBJ_Generic (without drawType).
|
|
239
|
+
|
|
240
|
+
| Property | Type | Default | Description |
|
|
241
|
+
|---|---|---|---|
|
|
242
|
+
| radius | number | | Radius |
|
|
243
|
+
| sides | number | `20` | Number of sides |
|
|
244
|
+
| startAngle | number | `0` | Start angle (radians) |
|
|
245
|
+
| angle | number | `1` | Arc angle (radians) |
|
|
246
|
+
| line | OBJ_LineStyleSimple | | Line style |
|
|
247
|
+
| fillCenter | boolean | | Fill to center point |
|
|
248
|
+
|
|
249
|
+
### OBJ_Triangle (`make: 'triangle'`)
|
|
250
|
+
Extends OBJ_Generic (without drawType).
|
|
251
|
+
|
|
252
|
+
Define by one of (highest precedence first): `points`, `ASA`, `SAS`, `AAS`, `SSS`, or `width`+`height`+`top`.
|
|
253
|
+
|
|
254
|
+
| Property | Type | Default | Description |
|
|
255
|
+
|---|---|---|---|
|
|
256
|
+
| points | Point[] | | Three defining points |
|
|
257
|
+
| width | number | | Base width |
|
|
258
|
+
| height | number | | Height |
|
|
259
|
+
| top | `'left'` \| `'right'` \| `'center'` | `'center'` | Top vertex position |
|
|
260
|
+
| SSS | [s1,s2,s3] | | Side-Side-Side |
|
|
261
|
+
| ASA | [a1,s1,a2] | | Angle-Side-Angle |
|
|
262
|
+
| AAS | [a1,a2,s1] | | Angle-Angle-Side |
|
|
263
|
+
| SAS | [s1,a1,s2] | | Side-Angle-Side |
|
|
264
|
+
| direction | `1` \| `-1` | `1` | Triangle above (1) or below (-1) base |
|
|
265
|
+
| rotation | number \| `'s1'` \| `'s2'` \| `'s3'` | | Rotation angle or relative to side |
|
|
266
|
+
| xAlign | string | `'centroid'` | X alignment: `'left'`, `'center'`, `'right'`, `'centroid'`, `'a1'`..`'a3'`, `'s1'`..`'s3'` |
|
|
267
|
+
| yAlign | string | `'centroid'` | Y alignment: `'bottom'`, `'middle'`, `'top'`, `'centroid'`, `'a1'`..`'a3'`, `'s1'`..`'s3'` |
|
|
268
|
+
| line | OBJ_LineStyleSimple | | Line style |
|
|
269
|
+
|
|
270
|
+
### OBJ_Line (`make: 'line'`)
|
|
271
|
+
Extends OBJ_Generic (without drawType).
|
|
272
|
+
|
|
273
|
+
| Property | Type | Default | Description |
|
|
274
|
+
|---|---|---|---|
|
|
275
|
+
| p1 | TypeParsablePoint | | Start point |
|
|
276
|
+
| p2 | TypeParsablePoint | | End point |
|
|
277
|
+
| length | number | | Length from p1 (alternative to p2) |
|
|
278
|
+
| angle | number | | Angle from p1 (alternative to p2) |
|
|
279
|
+
| width | number | `0.01` | Line width |
|
|
280
|
+
| widthIs | `'mid'` \| `'positive'` \| `'negative'` \| number | `'mid'` | Width direction |
|
|
281
|
+
| dash | number[] | | Dash pattern |
|
|
282
|
+
| arrow | OBJ_LineArrows \| TypeArrowHead | | Arrows on ends |
|
|
283
|
+
|
|
284
|
+
### OBJ_Arrow (`make: 'arrow'`)
|
|
285
|
+
Extends OBJ_Generic (without drawType).
|
|
286
|
+
|
|
287
|
+
| Property | Type | Default | Description |
|
|
288
|
+
|---|---|---|---|
|
|
289
|
+
| head | TypeArrowHead | `'triangle'` | `'triangle'`, `'barb'`, `'rectangle'`, `'line'`, `'polygon'`, `'circle'`, `'bar'`, `'reverseTriangle'` |
|
|
290
|
+
| scale | number | | Scale default dimensions |
|
|
291
|
+
| length | number | | Head length along line |
|
|
292
|
+
| width | number | | Head width |
|
|
293
|
+
| rotation | number | | Polygon head rotation |
|
|
294
|
+
| sides | number | | Polygon/circle sides |
|
|
295
|
+
| radius | number | | Polygon/circle radius |
|
|
296
|
+
| barb | number | | Barb length |
|
|
297
|
+
| tailWidth | number | | Tail line width |
|
|
298
|
+
| tail | boolean \| number | `false` | Include tail; number = tail length |
|
|
299
|
+
| align | `'tip'` \| `'start'` \| `'mid'` \| `'tail'` | `'tip'` | Which part at origin |
|
|
300
|
+
| angle | number | `0` | Drawing angle |
|
|
301
|
+
|
|
302
|
+
### OBJ_LineArrows (arrow config for lines/polylines)
|
|
303
|
+
|
|
304
|
+
| Property | Type | Default | Description |
|
|
305
|
+
|---|---|---|---|
|
|
306
|
+
| start | TypeArrowHead \| object | | Start arrow |
|
|
307
|
+
| end | TypeArrowHead \| object | | End arrow |
|
|
308
|
+
| scale | number | | Scale both arrows |
|
|
309
|
+
|
|
310
|
+
TypeArrowHead: `'triangle'` | `'barb'` | `'rectangle'` | `'line'` | `'polygon'` | `'circle'` | `'bar'` | `'reverseTriangle'`
|
|
311
|
+
|
|
312
|
+
### OBJ_Grid (`make: 'grid'`)
|
|
313
|
+
Extends OBJ_Generic (without drawType).
|
|
314
|
+
|
|
315
|
+
| Property | Type | Default | Description |
|
|
316
|
+
|---|---|---|---|
|
|
317
|
+
| bounds | [x,y,w,h] | | Grid rectangle |
|
|
318
|
+
| xStep | number | | Vertical line spacing |
|
|
319
|
+
| yStep | number | | Horizontal line spacing |
|
|
320
|
+
| xNum | number | | Number of vertical lines |
|
|
321
|
+
| yNum | number | | Number of horizontal lines |
|
|
322
|
+
| line | OBJ_LineStyleSimple | | Line style |
|
|
323
|
+
|
|
324
|
+
### OBJ_Text (`make: 'text'`)
|
|
325
|
+
|
|
326
|
+
| Property | Type | Default | Description |
|
|
327
|
+
|---|---|---|---|
|
|
328
|
+
| text | string \| string[] | | Text content |
|
|
329
|
+
| location | TypeParsablePoint \| TypeParsablePoint[] | `[0, 0]` | Position(s) |
|
|
330
|
+
| font | OBJ_Font | | Font (defaults to figure font) |
|
|
331
|
+
| xAlign | `'left'` \| `'center'` \| `'right'` | `'left'` | Horizontal alignment |
|
|
332
|
+
| yAlign | `'top'` \| `'bottom'` \| `'middle'` \| `'alphabetic'` \| `'baseline'` | `'baseline'` | Vertical alignment |
|
|
333
|
+
|
|
334
|
+
### OBJ_LineStyleSimple (used by polygon, rectangle, etc.)
|
|
335
|
+
|
|
336
|
+
| Property | Type | Default | Description |
|
|
337
|
+
|---|---|---|---|
|
|
338
|
+
| width | number | | Line width |
|
|
339
|
+
| widthIs | `'mid'` \| `'outside'` \| `'inside'` \| number | `'mid'` | Width direction |
|
|
340
|
+
| dash | number[] | | Dash pattern |
|
|
341
|
+
| color | TypeColor | | Line color |
|
|
342
|
+
|
|
343
|
+
### OBJ_GenericGL (`make: 'gl'`)
|
|
344
|
+
|
|
345
|
+
| Property | Type | Default | Description |
|
|
346
|
+
|---|---|---|---|
|
|
347
|
+
| glPrimitive | string | `'TRIANGLES'` | GL primitive type |
|
|
348
|
+
| vertexShader | object | | Custom vertex shader |
|
|
349
|
+
| fragmentShader | object | | Custom fragment shader |
|
|
350
|
+
| attributes | OBJ_GLAttribute[] | | Shader attributes |
|
|
351
|
+
| uniforms | OBJ_GLUniform[] | | Shader uniforms |
|
|
352
|
+
| texture | OBJ_Texture | | Texture |
|
|
353
|
+
| dimension | `2` \| `3` | `2` | Coordinate dimensions |
|
|
354
|
+
| light | `'directional'` \| `'point'` \| null | null | Lighting |
|
|
355
|
+
| vertices | number[] \| object | | Vertex data |
|
|
356
|
+
| colors | number[] \| object | | Per-vertex colors |
|
|
357
|
+
| normals | number[] \| object | | Normal vectors |
|
|
358
|
+
|
|
359
|
+
### OBJ_Morph (`make: 'morph'`)
|
|
360
|
+
|
|
361
|
+
Morphable shape with multiple point arrays that can be animated between.
|
|
362
|
+
|
|
363
|
+
| Property | Type | Default | Description |
|
|
364
|
+
|---|---|---|---|
|
|
365
|
+
| name | string | | Element name |
|
|
366
|
+
| pointArrays | number[][] | | Array of flat vertex arrays (each: [x1,y1,x2,y2,...]) |
|
|
367
|
+
| color | TypeColor \| TypeColor[] | | Color(s) per point array |
|
|
368
|
+
| names | string[] | | Name for each point array (usable in morph animation) |
|
|
369
|
+
| glPrimitive | `'TRIANGLES'` \| `'POINTS'` \| `'FAN'` \| `'STRIP'` \| `'LINES'` | `'TRIANGLES'` | GL primitive type |
|
|
370
|
+
|
|
371
|
+
```js
|
|
372
|
+
// Simple example
|
|
373
|
+
figure.add({
|
|
374
|
+
make: 'gl',
|
|
375
|
+
vertices: [0, 0, 0.5, 0, 0, 0.5],
|
|
376
|
+
color: [1, 0, 0, 1],
|
|
377
|
+
});
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## 4. 3D Shape Primitives
|
|
383
|
+
|
|
384
|
+
All 3D primitives extend OBJ_FigurePrimitive and OBJ_Generic3All.
|
|
385
|
+
|
|
386
|
+
### OBJ_Generic3All (base for all 3D shapes)
|
|
387
|
+
|
|
388
|
+
| Property | Type | Default | Description |
|
|
389
|
+
|---|---|---|---|
|
|
390
|
+
| light | `'directional'` \| `'point'` \| `'ambient'` \| null | `'directional'` | Lighting type |
|
|
391
|
+
| copy | CPY_Step[] \| CPY_Step | | Copy pattern |
|
|
392
|
+
| usage | `'STATIC'` \| `'DYNAMIC'` | `'STATIC'` | Buffer usage |
|
|
393
|
+
| touchScale | number \| TypeParsablePoint | | Touch scale |
|
|
394
|
+
|
|
395
|
+
### OBJ_Sphere (`make: 'sphere'`)
|
|
396
|
+
|
|
397
|
+
| Property | Type | Default | Description |
|
|
398
|
+
|---|---|---|---|
|
|
399
|
+
| sides | number | `10` | Sides around half great circle |
|
|
400
|
+
| radius | number | `1` | Sphere radius |
|
|
401
|
+
| normals | `'curve'` \| `'flat'` | `'flat'` | Shading style |
|
|
402
|
+
| center | TypeParsablePoint | `[0, 0]` | Center position |
|
|
403
|
+
| lines | boolean | `false` | Wire mesh mode |
|
|
404
|
+
|
|
405
|
+
### OBJ_Cube (`make: 'cube'`)
|
|
406
|
+
|
|
407
|
+
| Property | Type | Default | Description |
|
|
408
|
+
|---|---|---|---|
|
|
409
|
+
| side | number | `1` | Side length |
|
|
410
|
+
| center | TypeParsablePoint | `[0, 0]` | Center position |
|
|
411
|
+
| lines | boolean | `false` | Wire mesh mode |
|
|
412
|
+
|
|
413
|
+
### OBJ_Cylinder (`make: 'cylinder'`)
|
|
414
|
+
|
|
415
|
+
| Property | Type | Default | Description |
|
|
416
|
+
|---|---|---|---|
|
|
417
|
+
| sides | number | `10` | Number of sides |
|
|
418
|
+
| radius | number | `1` | Radius |
|
|
419
|
+
| normals | `'curve'` \| `'flat'` | `'flat'` | Shading style |
|
|
420
|
+
| line | [p1, p2] | | Position/orient via two points |
|
|
421
|
+
| length | number | `1` | Length (if `line` not defined) |
|
|
422
|
+
| ends | boolean \| `1` \| `2` | `true` | Fill ends: true=both, false=none, 1=first, 2=second |
|
|
423
|
+
| rotation | number | `0` | Base rotation |
|
|
424
|
+
|
|
425
|
+
### OBJ_Line3 (`make: 'line3'`)
|
|
426
|
+
|
|
427
|
+
| Property | Type | Default | Description |
|
|
428
|
+
|---|---|---|---|
|
|
429
|
+
| sides | number | `10` | Number of sides |
|
|
430
|
+
| p1 | TypeParsablePoint | `[0, 0, 0]` | Start point |
|
|
431
|
+
| p2 | TypeParsablePoint | `p1 + [1, 0, 0]` | End point |
|
|
432
|
+
| width | number | | Line width |
|
|
433
|
+
| arrow | OBJ_Line3Arrow \| boolean | | Arrows on ends |
|
|
434
|
+
| rotation | number | `0` | Rotation around axis |
|
|
435
|
+
| normals | `'curve'` \| `'flat'` | `'curve'` | Shading style |
|
|
436
|
+
|
|
437
|
+
### OBJ_Cone (`make: 'cone'`)
|
|
438
|
+
|
|
439
|
+
| Property | Type | Default | Description |
|
|
440
|
+
|---|---|---|---|
|
|
441
|
+
| sides | number | `10` | Number of sides |
|
|
442
|
+
| radius | number | | Base radius |
|
|
443
|
+
| normals | `'curve'` \| `'flat'` | `'flat'` | Shading style |
|
|
444
|
+
| line | [base, tip] | | Position/orient via two points |
|
|
445
|
+
| length | number | `1` | Length (if `line` not defined) |
|
|
446
|
+
| rotation | number | `0` | Base rotation |
|
|
447
|
+
| lines | boolean | `false` | Wire mesh mode |
|
|
448
|
+
|
|
449
|
+
### OBJ_Prism (`make: 'prism'`)
|
|
450
|
+
|
|
451
|
+
| Property | Type | Default | Description |
|
|
452
|
+
|---|---|---|---|
|
|
453
|
+
| base | TypeParsablePoint[] | | Base polygon points (XY plane, CCW) |
|
|
454
|
+
| baseTriangles | TypeParsablePoint[] | | Base triangulation (for non-convex) |
|
|
455
|
+
| length | number | | Prism length (into +z) |
|
|
456
|
+
| lines | boolean | `false` | Wire mesh mode |
|
|
457
|
+
|
|
458
|
+
### OBJ_Revolve (`make: 'revolve'`)
|
|
459
|
+
|
|
460
|
+
| Property | Type | Default | Description |
|
|
461
|
+
|---|---|---|---|
|
|
462
|
+
| profile | TypeParsablePoint[] | | XY plane profile (y >= 0) |
|
|
463
|
+
| sides | number | | Radial sweep sides |
|
|
464
|
+
| normals | `'flat'` \| `'curveProfile'` \| `'curveRadial'` \| `'curve'` | `'flat'` | Shading style |
|
|
465
|
+
| axis | TypeParsablePoint | | Orient shape axis |
|
|
466
|
+
| rotation | number | | Initial sweep angle |
|
|
467
|
+
| lines | boolean | `false` | Wire mesh mode |
|
|
468
|
+
|
|
469
|
+
### OBJ_Surface (`make: 'surface'`)
|
|
470
|
+
|
|
471
|
+
| Property | Type | Default | Description |
|
|
472
|
+
|---|---|---|---|
|
|
473
|
+
| points | TypeParsablePoint[][] | | 2D grid of 3D points |
|
|
474
|
+
| normals | `'flat'` \| `'curveColumns'` \| `'curveRows'` \| `'curve'` | `'flat'` | Shading style |
|
|
475
|
+
| closeRows | boolean | `false` | First/last row same (for curved normals) |
|
|
476
|
+
| closeColumns | boolean | `false` | First/last column same |
|
|
477
|
+
| lines | boolean | `false` | Wire mesh mode |
|
|
478
|
+
| invertNormals | boolean | | Invert all normals |
|
|
479
|
+
|
|
480
|
+
### OBJ_CameraControl (`make: 'cameraControl'`)
|
|
481
|
+
|
|
482
|
+
| Property | Type | Default | Description |
|
|
483
|
+
|---|---|---|---|
|
|
484
|
+
| left | number | `0` | Screen left (0-1) |
|
|
485
|
+
| bottom | number | `0` | Screen bottom (0-1) |
|
|
486
|
+
| width | number | `1` | Width (0-1) |
|
|
487
|
+
| height | number | `1` | Height (0-1) |
|
|
488
|
+
| axis | TypeParsablePoint | `[0, 1, 0]` | Vertical axis |
|
|
489
|
+
| controlScene | Scene \| string | | Scene to control (default: figure scene) |
|
|
490
|
+
| sensitivity | number | `5` | Overall sensitivity |
|
|
491
|
+
| xSensitivity | number | `1` | Horizontal sensitivity (0 = no azimuth) |
|
|
492
|
+
| ySensitivity | number | `1` | Vertical sensitivity (0 = no elevation) |
|
|
493
|
+
| back | boolean | `true` | Priority behind other touchable elements |
|
|
494
|
+
|
|
495
|
+
```js
|
|
496
|
+
// 3D setup
|
|
497
|
+
const figure = new Fig.Figure({ scene: { style: 'orthographic' } });
|
|
498
|
+
figure.add([
|
|
499
|
+
{ make: 'sphere', radius: 0.3, color: [1, 0, 0, 1], normals: 'curve' },
|
|
500
|
+
{ make: 'cameraControl' },
|
|
501
|
+
]);
|
|
502
|
+
|
|
503
|
+
// Surface from function
|
|
504
|
+
const points = Fig.surfaceGrid({
|
|
505
|
+
x: [-0.8, 0.8, 0.02], y: [-0.8, 0.8, 0.02],
|
|
506
|
+
z: (x, y) => Math.sin(Math.sqrt(x*x + y*y) * 4) * 0.3,
|
|
507
|
+
});
|
|
508
|
+
figure.add({ make: 'surface', points, color: [1, 0, 0, 1], normals: 'curve' });
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
---
|
|
512
|
+
|
|
513
|
+
## 5. Collections
|
|
514
|
+
|
|
515
|
+
Collections are higher-level compound elements. Use `make: 'collections.type'`.
|
|
516
|
+
|
|
517
|
+
### COL_Plot (`make: 'collections.plot'`)
|
|
518
|
+
|
|
519
|
+
| Property | Type | Default | Description |
|
|
520
|
+
|---|---|---|---|
|
|
521
|
+
| width | number | | Plot area width |
|
|
522
|
+
| height | number | | Plot area height |
|
|
523
|
+
| x | object \| boolean | | X axis config or `false` to hide |
|
|
524
|
+
| y | object \| boolean | | Y axis config or `false` to hide |
|
|
525
|
+
| trace | COL_Trace \| COL_Trace[] \| point[] | | Trace data |
|
|
526
|
+
| legend | COL_PlotLegend | | Legend options |
|
|
527
|
+
| title | string \| object | | Plot title |
|
|
528
|
+
| grid | boolean | | Show grid |
|
|
529
|
+
| cross | TypeParsablePoint \| null | | Where axes cross |
|
|
530
|
+
| frame | boolean \| TypeColor \| object | | Frame around plot |
|
|
531
|
+
| plotArea | TypeColor \| object | | Plot area background |
|
|
532
|
+
| font | OBJ_Font | | Default font |
|
|
533
|
+
| color | TypeColor | | Default color |
|
|
534
|
+
| position | TypeParsablePoint | | Position |
|
|
535
|
+
| zoom | object \| `'x'` \| `'y'` \| `'xy'` | | Zoom options |
|
|
536
|
+
| pan | object \| `'x'` \| `'y'` \| `'xy'` | | Pan options |
|
|
537
|
+
| styleTheme | `'box'` \| `'numberLine'` \| `'positiveNumberLine'` | `'box'` | Theme |
|
|
538
|
+
| colorTheme | `'light'` \| `'dark'` | `'dark'` | Color theme |
|
|
539
|
+
| autoGrid | boolean | `true` | Expand grid across plot |
|
|
540
|
+
|
|
541
|
+
### COL_Trace (used within COL_Plot)
|
|
542
|
+
|
|
543
|
+
| Property | Type | Default | Description |
|
|
544
|
+
|---|---|---|---|
|
|
545
|
+
| points | TypeParsablePoint[] | | Trace data points |
|
|
546
|
+
| x | number[] | | X values (alternative to points) |
|
|
547
|
+
| y | number[] | | Y values (alternative to points) |
|
|
548
|
+
| line | OBJ_LineStyleSimple | | Line style |
|
|
549
|
+
| markers | OBJ_Polygon \| OBJ_Star | | Marker shape |
|
|
550
|
+
| color | TypeColor | | Trace color |
|
|
551
|
+
| name | string | | Name for legend |
|
|
552
|
+
|
|
553
|
+
### COL_PlotLegend
|
|
554
|
+
|
|
555
|
+
| Property | Type | Default | Description |
|
|
556
|
+
|---|---|---|---|
|
|
557
|
+
| position | TypeParsablePoint | | Legend position |
|
|
558
|
+
| length | number | | Line sample length |
|
|
559
|
+
| space | number | | Space between line and text |
|
|
560
|
+
| offset | TypeParsablePoint | | Offset between traces |
|
|
561
|
+
| font | OBJ_Font | | Legend font |
|
|
562
|
+
| fontColorIsLineColor | boolean | | Match text to line color |
|
|
563
|
+
| frame | object | | Frame around legend |
|
|
564
|
+
|
|
565
|
+
```js
|
|
566
|
+
// Plot with multiple traces
|
|
567
|
+
figure.add({
|
|
568
|
+
make: 'collections.plot',
|
|
569
|
+
width: 1, height: 1, position: [-0.5, -0.5],
|
|
570
|
+
x: { title: 'time (s)' },
|
|
571
|
+
y: { start: 0, stop: 100, title: 'distance (m)' },
|
|
572
|
+
trace: [
|
|
573
|
+
{ points: data1, name: 'Linear' },
|
|
574
|
+
{ points: data2, name: 'Quadratic', markers: { sides: 4, radius: 0.02 } },
|
|
575
|
+
],
|
|
576
|
+
legend: { font: { size: 0.05 } },
|
|
577
|
+
});
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### COL_Axis (`make: 'collections.axis'`)
|
|
581
|
+
|
|
582
|
+
| Property | Type | Default | Description |
|
|
583
|
+
|---|---|---|---|
|
|
584
|
+
| axis | `'x'` \| `'y'` | `'x'` | Orientation |
|
|
585
|
+
| length | number | | Axis length |
|
|
586
|
+
| start | number | `0` | Start value |
|
|
587
|
+
| stop | number | `start + 1` | Stop value |
|
|
588
|
+
| step | number | | Tick/label step |
|
|
589
|
+
| line | boolean \| object | | Axis line |
|
|
590
|
+
| ticks | object \| boolean | `false` | Tick marks |
|
|
591
|
+
| labels | object \| boolean \| string | | Axis labels |
|
|
592
|
+
| grid | object \| boolean | `false` | Grid lines |
|
|
593
|
+
| title | string \| object | | Axis title |
|
|
594
|
+
| font | OBJ_Font | | Default font |
|
|
595
|
+
| show | boolean | `true` | Show/hide axis |
|
|
596
|
+
| min | number \| null | `null` | Min value (zoom/pan limit) |
|
|
597
|
+
| max | number \| null | `null` | Max value (zoom/pan limit) |
|
|
598
|
+
| position | TypeParsablePoint | `[0, 0]` | Axis position |
|
|
599
|
+
| values | number[] | | Custom tick/label values |
|
|
600
|
+
| auto | [number, number] | | Auto-select start/stop/step from data range |
|
|
601
|
+
|
|
602
|
+
#### Axis Ticks Configuration
|
|
603
|
+
When `ticks` is an object:
|
|
604
|
+
|
|
605
|
+
| Property | Type | Default | Description |
|
|
606
|
+
|---|---|---|---|
|
|
607
|
+
| step | number | | Tick step (overrides axis step) |
|
|
608
|
+
| start | number | | Start value for ticks |
|
|
609
|
+
| stop | number | | Stop value for ticks |
|
|
610
|
+
| length | number | `0.1` | Tick length |
|
|
611
|
+
| width | number | | Tick width |
|
|
612
|
+
| offset | number | `0` | Offset from axis |
|
|
613
|
+
| color | TypeColor | | Tick color |
|
|
614
|
+
| values | number[] | | Custom tick positions |
|
|
615
|
+
|
|
616
|
+
#### Axis Labels Configuration
|
|
617
|
+
When `labels` is an object:
|
|
618
|
+
|
|
619
|
+
| Property | Type | Default | Description |
|
|
620
|
+
|---|---|---|---|
|
|
621
|
+
| step | number | | Label step (overrides axis step) |
|
|
622
|
+
| start | number | | Start value for labels |
|
|
623
|
+
| stop | number | | Stop value for labels |
|
|
624
|
+
| font | OBJ_Font | | Label font |
|
|
625
|
+
| precision | number | | Decimal precision |
|
|
626
|
+
| format | function | | Custom format: `(value) => string` |
|
|
627
|
+
| offset | TypeParsablePoint | | Label offset |
|
|
628
|
+
| rotation | number | | Label rotation |
|
|
629
|
+
| values | number[] | | Custom label positions |
|
|
630
|
+
| hide | number[] | | Values to hide labels for |
|
|
631
|
+
| text | string[] | | Custom text per label position |
|
|
632
|
+
|
|
633
|
+
#### Axis Grid Configuration
|
|
634
|
+
When `grid` is an object:
|
|
635
|
+
|
|
636
|
+
| Property | Type | Default | Description |
|
|
637
|
+
|---|---|---|---|
|
|
638
|
+
| step | number | | Grid step |
|
|
639
|
+
| length | number | | Grid line length |
|
|
640
|
+
| width | number | | Grid line width |
|
|
641
|
+
| color | TypeColor | | Grid color |
|
|
642
|
+
| dash | number[] | | Dash pattern |
|
|
643
|
+
|
|
644
|
+
```js
|
|
645
|
+
// Detailed axis example
|
|
646
|
+
figure.add({
|
|
647
|
+
make: 'collections.axis',
|
|
648
|
+
axis: 'x', length: 2, start: -5, stop: 5, step: 1,
|
|
649
|
+
position: [-1, 0],
|
|
650
|
+
ticks: { length: 0.05, offset: -0.025 },
|
|
651
|
+
labels: { precision: 0, offset: [0, -0.1], hide: [0] },
|
|
652
|
+
grid: { length: 2, width: 0.002, dash: [0.01, 0.01], color: [0.5, 0.5, 0.5, 0.3] },
|
|
653
|
+
title: { text: 'x', offset: [0, -0.2] },
|
|
654
|
+
});
|
|
655
|
+
```
|
|
656
|
+
|
|
657
|
+
### COL_Axis3 (`make: 'collections.axis3'`)
|
|
658
|
+
|
|
659
|
+
| Property | Type | Default | Description |
|
|
660
|
+
|---|---|---|---|
|
|
661
|
+
| width | number \| [x,y,z] | | Axis width |
|
|
662
|
+
| length | number \| [x,y,z] | | Axis length |
|
|
663
|
+
| start | number \| [x,y,z] | `0` | Start value |
|
|
664
|
+
| sides | number \| [x,y,z] | `10` | Cross-section sides |
|
|
665
|
+
| lines | boolean \| [x,y,z] | `false` | Wire mesh mode |
|
|
666
|
+
| arrow | object \| boolean | | Arrow options |
|
|
667
|
+
| color | TypeColor \| [x,y,z] | red, green, blue | Per-axis colors |
|
|
668
|
+
|
|
669
|
+
### COL_Line (`make: 'collections.line'` or `'oline'`)
|
|
670
|
+
|
|
671
|
+
| Property | Type | Default | Description |
|
|
672
|
+
|---|---|---|---|
|
|
673
|
+
| p1 | TypeParsablePoint | | Start point |
|
|
674
|
+
| p2 | TypeParsablePoint | | End point |
|
|
675
|
+
| angle | number | | Line angle (alternative to p2) |
|
|
676
|
+
| length | number | | Line length (alternative to p2) |
|
|
677
|
+
| offset | number | | Line offset |
|
|
678
|
+
| align | `'start'` \| `'end'` \| `'center'` \| number | | Rotation center |
|
|
679
|
+
| width | number | | Line width |
|
|
680
|
+
| label | OBJ_LineLabel | | Label annotation |
|
|
681
|
+
| arrow | OBJ_LineArrows \| TypeArrowHead | | Arrows |
|
|
682
|
+
| dash | number[] | | Dash pattern |
|
|
683
|
+
| move | object | | Move options |
|
|
684
|
+
|
|
685
|
+
### COL_Angle (`make: 'collections.angle'` or `'angle'`)
|
|
686
|
+
|
|
687
|
+
| Property | Type | Default | Description |
|
|
688
|
+
|---|---|---|---|
|
|
689
|
+
| position | Point | | Vertex position |
|
|
690
|
+
| startAngle | number | | Start angle |
|
|
691
|
+
| angle | number | | Angle size |
|
|
692
|
+
| p1 | Point | | Point on first ray (alternative) |
|
|
693
|
+
| p2 | Point | | Vertex point (alternative) |
|
|
694
|
+
| p3 | Point | | Point on second ray (alternative) |
|
|
695
|
+
| direction | `1` \| `-1` | | Annotation side |
|
|
696
|
+
| curve | object | | Curve annotation options |
|
|
697
|
+
| arrow | object | | Arrow annotation options |
|
|
698
|
+
| corner | object | | Corner drawing options |
|
|
699
|
+
| label | object | | Label options |
|
|
700
|
+
|
|
701
|
+
### COL_Polyline (`make: 'collections.polyline'` or `'opolyline'`)
|
|
702
|
+
Extends OBJ_Polyline properties.
|
|
703
|
+
|
|
704
|
+
| Property | Type | Default | Description |
|
|
705
|
+
|---|---|---|---|
|
|
706
|
+
| showLine | boolean | `true` | Show the line |
|
|
707
|
+
| angle | object \| COL_Angle[] | | Angle annotations |
|
|
708
|
+
| side | object \| COL_Line[] | | Side annotations |
|
|
709
|
+
| pad | object | | Move pad options |
|
|
710
|
+
| makeValid | object \| null | | Shape consistency enforcement |
|
|
711
|
+
| font | OBJ_Font | | Default label font |
|
|
712
|
+
|
|
713
|
+
### COL_Rectangle (`make: 'collections.rectangle'`)
|
|
714
|
+
|
|
715
|
+
| Property | Type | Default | Description |
|
|
716
|
+
|---|---|---|---|
|
|
717
|
+
| width | number | | Width |
|
|
718
|
+
| height | number | | Height |
|
|
719
|
+
| xAlign | `'left'` \| `'center'` \| `'right'` \| number | | X alignment |
|
|
720
|
+
| yAlign | `'bottom'` \| `'middle'` \| `'top'` \| number | | Y alignment |
|
|
721
|
+
| line | OBJ_LineStyleSimple | | Outline style |
|
|
722
|
+
| fill | TypeColor \| OBJ_Texture | | Fill |
|
|
723
|
+
| corner | OBJ_CurvedCorner | | Rounded corners |
|
|
724
|
+
| label | OBJ_FormattedText | | Label |
|
|
725
|
+
| button | boolean \| TypeColor | `false` | Button behavior |
|
|
726
|
+
|
|
727
|
+
### COL_Slider (`make: 'collections.slider'`)
|
|
728
|
+
|
|
729
|
+
| Property | Type | Default | Description |
|
|
730
|
+
|---|---|---|---|
|
|
731
|
+
| width | number | | Slider width |
|
|
732
|
+
| height | number | | Slider height |
|
|
733
|
+
| barHeight | number | | Bar height |
|
|
734
|
+
| marker | object \| `'polygon'` \| `'rectangle'` \| `'none'` | `'polygon'` | Marker style |
|
|
735
|
+
| sides | number | `20` | Curve sides |
|
|
736
|
+
| theme | `'dark'` \| `'light'` | `'dark'` | Color theme |
|
|
737
|
+
| colorOff | TypeColor | | Off color |
|
|
738
|
+
| colorOn | TypeColor | `[0, 1, 0, 1]` | On color |
|
|
739
|
+
|
|
740
|
+
### COL_Toggle (`make: 'collections.toggle'`)
|
|
741
|
+
|
|
742
|
+
| Property | Type | Default | Description |
|
|
743
|
+
|---|---|---|---|
|
|
744
|
+
| width | number | | Toggle width |
|
|
745
|
+
| height | number | | Toggle height |
|
|
746
|
+
| barHeight | number | | Bar height |
|
|
747
|
+
| sides | number | `20` | Curve sides |
|
|
748
|
+
| theme | `'dark'` \| `'light'` | `'dark'` | Color theme |
|
|
749
|
+
| colorOff | TypeColor | | Off color |
|
|
750
|
+
| colorOn | TypeColor | `[0, 1, 0, 1]` | On color |
|
|
751
|
+
| label | object | | Label options |
|
|
752
|
+
|
|
753
|
+
### COL_Button (`make: 'collections.button'`)
|
|
754
|
+
|
|
755
|
+
| Property | Type | Default | Description |
|
|
756
|
+
|---|---|---|---|
|
|
757
|
+
| width | number | | Button width |
|
|
758
|
+
| height | number | | Button height |
|
|
759
|
+
| corner | OBJ_CurvedCorner | | Corner rounding |
|
|
760
|
+
| line | OBJ_LineStyleSimple \| null | | Outline |
|
|
761
|
+
| label | object | | Label |
|
|
762
|
+
| colorLine | TypeColor | | Line color |
|
|
763
|
+
| colorFill | TypeColor | | Fill color |
|
|
764
|
+
| colorLabel | TypeColor | | Label color |
|
|
765
|
+
| touchDown | object | | Touch-down colors |
|
|
766
|
+
| states | array | | Button state definitions |
|
|
767
|
+
|
|
768
|
+
### OBJ_FormattedText (`make: 'ftext'`)
|
|
769
|
+
|
|
770
|
+
| Property | Type | Default | Description |
|
|
771
|
+
|---|---|---|---|
|
|
772
|
+
| text | string \| string[] | | Text lines |
|
|
773
|
+
| modifiers | OBJ_TextModifiersDefinition | | Inline formatting modifiers |
|
|
774
|
+
| elements | object | | Equation elements |
|
|
775
|
+
| font | OBJ_Font | | Default font |
|
|
776
|
+
| justify | `'left'` \| `'center'` \| `'right'` | `'left'` | Line justification |
|
|
777
|
+
| lineSpace | number | `font.size * 0.5` | Line spacing |
|
|
778
|
+
| xAlign | `'left'` \| `'center'` \| `'right'` | `'left'` | Horizontal alignment |
|
|
779
|
+
| yAlign | `'bottom'` \| `'baseline'` \| `'middle'` \| `'top'` | `'baseline'` | Vertical alignment |
|
|
780
|
+
| accent | OBJ_Font | italic | Default modifier style |
|
|
781
|
+
|
|
782
|
+
### OBJ_TextModifierDefinition (inline text modifier)
|
|
783
|
+
|
|
784
|
+
| Property | Type | Default | Description |
|
|
785
|
+
|---|---|---|---|
|
|
786
|
+
| text | string | modifierId | Replacement text (default: use the modifier key) |
|
|
787
|
+
| offset | TypeParsablePoint | | Text offset |
|
|
788
|
+
| followOffsetY | boolean | `false` | Subsequent text shares y offset |
|
|
789
|
+
| font | OBJ_Font | | Font changes for modified text |
|
|
790
|
+
| inLine | boolean | `true` | `false` to exclude from line layout |
|
|
791
|
+
| onClick | string \| function | | Click callback |
|
|
792
|
+
| touchBorder | buffer \| Point[] | `0` | Touch border |
|
|
793
|
+
|
|
794
|
+
```js
|
|
795
|
+
// Formatted text with clickable modifier
|
|
796
|
+
figure.add({
|
|
797
|
+
make: 'ftext',
|
|
798
|
+
text: 'Click |here| to start',
|
|
799
|
+
modifiers: {
|
|
800
|
+
here: {
|
|
801
|
+
font: { color: [0, 0, 1, 1] },
|
|
802
|
+
onClick: () => console.log('clicked'),
|
|
803
|
+
touchBorder: 0.03,
|
|
804
|
+
},
|
|
805
|
+
},
|
|
806
|
+
});
|
|
807
|
+
```
|
|
808
|
+
|
|
809
|
+
---
|
|
810
|
+
|
|
811
|
+
## 6. Equation System
|
|
812
|
+
|
|
813
|
+
Create with `make: 'equation'`. Define `elements` (terms and symbols) and `forms` (layouts).
|
|
814
|
+
|
|
815
|
+
### EQN_Equation
|
|
816
|
+
|
|
817
|
+
| Property | Type | Default | Description |
|
|
818
|
+
|---|---|---|---|
|
|
819
|
+
| color | TypeColor | | Equation color |
|
|
820
|
+
| dimColor | TypeColor | | Dim color |
|
|
821
|
+
| font | OBJ_Font | | Math font |
|
|
822
|
+
| textFont | OBJ_Font | `font` | Text font |
|
|
823
|
+
| scale | number | `0.7` | Equation scale |
|
|
824
|
+
| elements | object | | Element definitions |
|
|
825
|
+
| forms | object | | Form definitions |
|
|
826
|
+
| formDefaults | object | | Default form options |
|
|
827
|
+
| initialForm | string | | Initial form to show |
|
|
828
|
+
| formSeries | object | | Named series of forms |
|
|
829
|
+
| defaultFormSeries | string | | Default series name |
|
|
830
|
+
| phrases | object | | Reusable sub-expressions |
|
|
831
|
+
| position | TypeParsablePoint | | Position |
|
|
832
|
+
| transform | Transform | | Transform |
|
|
833
|
+
|
|
834
|
+
### Elements
|
|
835
|
+
|
|
836
|
+
Elements are defined as an object where keys are element names. String values auto-create text elements. Objects define symbols or styled text.
|
|
837
|
+
|
|
838
|
+
```js
|
|
839
|
+
elements: {
|
|
840
|
+
v: { symbol: 'vinculum' },
|
|
841
|
+
equals: ' = ',
|
|
842
|
+
times: ' × ',
|
|
843
|
+
c: { color: [0, 0, 1, 1] }, // colored text 'c'
|
|
844
|
+
}
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
- Undeclared strings in forms auto-create text elements
|
|
848
|
+
- `'_ + '` prefix creates element with display text ` + ` (underscore is stripped)
|
|
849
|
+
- `'b_1'`, `'b_2'` create copies that display as `b`
|
|
850
|
+
|
|
851
|
+
### Symbols
|
|
852
|
+
|
|
853
|
+
Define in elements with `{ symbol: 'type', ...options }`. All symbols accept base properties: `color`, `isTouchable`, `touchBorder`, `onClick`, `mods`.
|
|
854
|
+
|
|
855
|
+
#### EQN_VinculumSymbol (`symbol: 'vinculum'`)
|
|
856
|
+
|
|
857
|
+
| Property | Type | Default | Description |
|
|
858
|
+
|---|---|---|---|
|
|
859
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
860
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | `'dynamic'` updates vertices on resize, `'static'` only changes scale |
|
|
861
|
+
| staticWidth | number \| `'first'` | `'first'` | Width for static draw mode |
|
|
862
|
+
|
|
863
|
+
#### EQN_BoxSymbol (`symbol: 'box'`)
|
|
864
|
+
|
|
865
|
+
| Property | Type | Default | Description |
|
|
866
|
+
|---|---|---|---|
|
|
867
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
868
|
+
| fill | boolean | `false` | Fill box instead of outline |
|
|
869
|
+
| width | number | | Force width |
|
|
870
|
+
| height | number | | Force height |
|
|
871
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
872
|
+
|
|
873
|
+
#### EQN_BracketSymbol (`symbol: 'bracket'`)
|
|
874
|
+
|
|
875
|
+
| Property | Type | Default | Description |
|
|
876
|
+
|---|---|---|---|
|
|
877
|
+
| side | `'left'` \| `'right'` \| `'top'` \| `'bottom'` | `'left'` | Bracket side |
|
|
878
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
879
|
+
| sides | number | `10` | Curve segments |
|
|
880
|
+
| tipWidth | number | | Tip thickness (default: 0) |
|
|
881
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
882
|
+
|
|
883
|
+
#### EQN_SquareBracketSymbol (`symbol: 'squareBracket'`)
|
|
884
|
+
|
|
885
|
+
| Property | Type | Default | Description |
|
|
886
|
+
|---|---|---|---|
|
|
887
|
+
| side | `'left'` \| `'right'` \| `'top'` \| `'bottom'` | `'left'` | Bracket side |
|
|
888
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
889
|
+
| tipWidth | number | `0.01` | Tip width |
|
|
890
|
+
| radius | number | `0` | Corner radius |
|
|
891
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
892
|
+
|
|
893
|
+
#### EQN_AngleBracketSymbol (`symbol: 'angleBracket'`)
|
|
894
|
+
|
|
895
|
+
| Property | Type | Default | Description |
|
|
896
|
+
|---|---|---|---|
|
|
897
|
+
| side | `'left'` \| `'right'` \| `'top'` \| `'bottom'` | `'left'` | Bracket side |
|
|
898
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
899
|
+
| width | number | | Bracket width |
|
|
900
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
901
|
+
|
|
902
|
+
#### EQN_BraceSymbol (`symbol: 'brace'`)
|
|
903
|
+
|
|
904
|
+
| Property | Type | Default | Description |
|
|
905
|
+
|---|---|---|---|
|
|
906
|
+
| side | `'left'` \| `'right'` \| `'top'` \| `'bottom'` | `'left'` | Brace side |
|
|
907
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
908
|
+
| sides | number | `10` | Curve segments |
|
|
909
|
+
| width | number | | Brace width |
|
|
910
|
+
| tipWidth | number | | Tip width |
|
|
911
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
912
|
+
|
|
913
|
+
#### EQN_BarSymbol (`symbol: 'bar'`)
|
|
914
|
+
|
|
915
|
+
| Property | Type | Default | Description |
|
|
916
|
+
|---|---|---|---|
|
|
917
|
+
| side | `'left'` \| `'right'` \| `'top'` \| `'bottom'` | `'left'` | Bar side |
|
|
918
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
919
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
920
|
+
|
|
921
|
+
#### EQN_RadicalSymbol (`symbol: 'radical'`)
|
|
922
|
+
|
|
923
|
+
| Property | Type | Default | Description |
|
|
924
|
+
|---|---|---|---|
|
|
925
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
926
|
+
| startWidth | number | `0.5` | Start stroke width ratio |
|
|
927
|
+
| startHeight | number | `0.5` | Start stroke height ratio |
|
|
928
|
+
| proportionalToHeight | boolean | `true` | Scale proportionally |
|
|
929
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
930
|
+
|
|
931
|
+
#### EQN_StrikeSymbol (`symbol: 'strike'`)
|
|
932
|
+
|
|
933
|
+
| Property | Type | Default | Description |
|
|
934
|
+
|---|---|---|---|
|
|
935
|
+
| style | `'cross'` \| `'forward'` \| `'back'` \| `'horizontal'` | `'cross'` | Strike pattern |
|
|
936
|
+
| lineWidth | number | `0.015` | Line thickness |
|
|
937
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
938
|
+
|
|
939
|
+
#### EQN_IntegralSymbol (`symbol: 'int'`)
|
|
940
|
+
|
|
941
|
+
| Property | Type | Default | Description |
|
|
942
|
+
|---|---|---|---|
|
|
943
|
+
| num | number | `1` | Number of integrals |
|
|
944
|
+
| type | `'generic'` \| `'line'` | `'generic'` | Style |
|
|
945
|
+
| sides | number | `30` | Curve segments |
|
|
946
|
+
| lineWidth | number | `0.01` | Line width |
|
|
947
|
+
| width | number | | Symbol width |
|
|
948
|
+
| serif | boolean | `true` | Show serifs |
|
|
949
|
+
| space | number | | Space between multiple integrals |
|
|
950
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
951
|
+
|
|
952
|
+
#### EQN_SumSymbol (`symbol: 'sum'`)
|
|
953
|
+
|
|
954
|
+
| Property | Type | Default | Description |
|
|
955
|
+
|---|---|---|---|
|
|
956
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
957
|
+
| sides | number | `5` | Serif segments |
|
|
958
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
959
|
+
|
|
960
|
+
#### EQN_ProdSymbol (`symbol: 'prod'`)
|
|
961
|
+
|
|
962
|
+
| Property | Type | Default | Description |
|
|
963
|
+
|---|---|---|---|
|
|
964
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
965
|
+
| sides | number | `5` | Serif segments |
|
|
966
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
967
|
+
|
|
968
|
+
#### EQN_ArrowSymbol (`symbol: 'arrow'`)
|
|
969
|
+
|
|
970
|
+
| Property | Type | Default | Description |
|
|
971
|
+
|---|---|---|---|
|
|
972
|
+
| direction | `'right'` \| `'left'` \| `'up'` \| `'down'` | `'right'` | Arrow direction |
|
|
973
|
+
| lineWidth | number | `0.01` | Line width |
|
|
974
|
+
| arrowWidth | number | `0.04` | Arrow head width |
|
|
975
|
+
| arrowLength | number | `0.04` | Arrow head length |
|
|
976
|
+
| draw | `'static'` \| `'dynamic'` | `'dynamic'` | Resize behavior |
|
|
977
|
+
|
|
978
|
+
#### EQN_LineSymbol (`symbol: 'line'`)
|
|
979
|
+
|
|
980
|
+
| Property | Type | Default | Description |
|
|
981
|
+
|---|---|---|---|
|
|
982
|
+
| width | number | `0.01` | Line width |
|
|
983
|
+
| dash | number[] | | Dash pattern |
|
|
984
|
+
| arrow | OBJ_LineArrows | | Arrow on end(s) |
|
|
985
|
+
|
|
986
|
+
#### EQN_DivisionSymbol (`symbol: 'division'`)
|
|
987
|
+
|
|
988
|
+
| Property | Type | Default | Description |
|
|
989
|
+
|---|---|---|---|
|
|
990
|
+
| lineWidth | number | `0.01` | Line thickness |
|
|
991
|
+
| radius | number | `0.03` | Dot radius |
|
|
992
|
+
| sides | number | `20` | Dot sides |
|
|
993
|
+
| space | number | `0.04` | Dot-to-line space |
|
|
994
|
+
|
|
995
|
+
### Layout Functions
|
|
996
|
+
|
|
997
|
+
Used in form definitions. Array syntax and object syntax are both supported. Below are the full property tables for each layout function's object syntax.
|
|
998
|
+
|
|
999
|
+
#### EQN_Fraction (`frac`)
|
|
1000
|
+
Array: `{ frac: [numerator, symbol, denominator] }`
|
|
1001
|
+
|
|
1002
|
+
| Property | Type | Default | Description |
|
|
1003
|
+
|---|---|---|---|
|
|
1004
|
+
| numerator | TypeEquationPhrase | | Numerator content |
|
|
1005
|
+
| symbol | string | | Vinculum symbol name |
|
|
1006
|
+
| denominator | TypeEquationPhrase | | Denominator content |
|
|
1007
|
+
| scale | number | `1` | Content scale |
|
|
1008
|
+
| numeratorSpace | number | `0.05` | Space above vinculum |
|
|
1009
|
+
| denominatorSpace | number | `0.05` | Space below vinculum |
|
|
1010
|
+
| overhang | number | `0.05` | Vinculum extends beyond content |
|
|
1011
|
+
| offsetY | number | `0.07` | Vertical offset of fraction |
|
|
1012
|
+
| baseline | `'numerator'` \| `'denominator'` \| `'vinculum'` | | Baseline alignment |
|
|
1013
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1014
|
+
|
|
1015
|
+
#### EQN_Superscript (`sup`)
|
|
1016
|
+
Array: `{ sup: [content, superscript] }`
|
|
1017
|
+
|
|
1018
|
+
| Property | Type | Default | Description |
|
|
1019
|
+
|---|---|---|---|
|
|
1020
|
+
| content | TypeEquationPhrase | | Base content |
|
|
1021
|
+
| superscript | TypeEquationPhrase | | Superscript content |
|
|
1022
|
+
| scale | number | `0.5` | Superscript scale |
|
|
1023
|
+
| offset | TypeParsablePoint | `[0, 0]` | Superscript offset |
|
|
1024
|
+
| inSize | boolean | `true` | Include in phrase size |
|
|
1025
|
+
|
|
1026
|
+
#### EQN_Subscript (`sub`)
|
|
1027
|
+
Array: `{ sub: [content, subscript] }`
|
|
1028
|
+
|
|
1029
|
+
| Property | Type | Default | Description |
|
|
1030
|
+
|---|---|---|---|
|
|
1031
|
+
| content | TypeEquationPhrase | | Base content |
|
|
1032
|
+
| subscript | TypeEquationPhrase | | Subscript content |
|
|
1033
|
+
| scale | number | `0.5` | Subscript scale |
|
|
1034
|
+
| offset | TypeParsablePoint | `[0, 0]` | Subscript offset |
|
|
1035
|
+
| inSize | boolean | `true` | Include in phrase size |
|
|
1036
|
+
|
|
1037
|
+
#### EQN_SuperscriptSubscript (`supSub`)
|
|
1038
|
+
Array: `{ supSub: [content, superscript, subscript] }`
|
|
1039
|
+
|
|
1040
|
+
| Property | Type | Default | Description |
|
|
1041
|
+
|---|---|---|---|
|
|
1042
|
+
| content | TypeEquationPhrase | | Base content |
|
|
1043
|
+
| superscript | TypeEquationPhrase | | Superscript content |
|
|
1044
|
+
| subscript | TypeEquationPhrase | | Subscript content |
|
|
1045
|
+
| scale | number | `0.5` | Script scale |
|
|
1046
|
+
| superscriptOffset | TypeParsablePoint | `[0, 0]` | Superscript offset |
|
|
1047
|
+
| subscriptOffset | TypeParsablePoint | `[0, 0]` | Subscript offset |
|
|
1048
|
+
| inSize | boolean | `true` | Include in phrase size |
|
|
1049
|
+
|
|
1050
|
+
#### EQN_Bracket (`brac`)
|
|
1051
|
+
Array: `{ brac: [left_symbol, content, right_symbol] }`
|
|
1052
|
+
|
|
1053
|
+
| Property | Type | Default | Description |
|
|
1054
|
+
|---|---|---|---|
|
|
1055
|
+
| left | string | | Left bracket symbol |
|
|
1056
|
+
| content | TypeEquationPhrase | | Content |
|
|
1057
|
+
| right | string | | Right bracket symbol |
|
|
1058
|
+
| inSize | boolean | `true` | Include brackets in size |
|
|
1059
|
+
| insideSpace | number | `0.03` | Space between brackets and content |
|
|
1060
|
+
| outsideSpace | number | `0.03` | Space between brackets and neighbors |
|
|
1061
|
+
| topSpace | number | `0.05` | Bracket extends above content |
|
|
1062
|
+
| bottomSpace | number | `0.05` | Bracket extends below content |
|
|
1063
|
+
| minContentHeight | number \| null | `null` | Min content height for bracket sizing |
|
|
1064
|
+
| minContentDescent | number \| null | `null` | Min content descent |
|
|
1065
|
+
| height | number \| null | `null` | Force bracket height |
|
|
1066
|
+
| descent | number \| null | `null` | Force bracket descent |
|
|
1067
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1068
|
+
| useFullBounds | boolean | `false` | Resulting phrase uses full bounds |
|
|
1069
|
+
|
|
1070
|
+
#### EQN_Root (`root`)
|
|
1071
|
+
Array: `{ root: [radical_symbol, content] }`
|
|
1072
|
+
|
|
1073
|
+
| Property | Type | Default | Description |
|
|
1074
|
+
|---|---|---|---|
|
|
1075
|
+
| symbol | string | | Radical symbol name |
|
|
1076
|
+
| content | TypeEquationPhrase | | Content under radical |
|
|
1077
|
+
| inSize | boolean | `true` | Include radical in size |
|
|
1078
|
+
| space | number | `0.02` | Default space (all directions) |
|
|
1079
|
+
| topSpace | number | `space` | Space above content |
|
|
1080
|
+
| rightSpace | number | `space` | Radical overhang right |
|
|
1081
|
+
| bottomSpace | number | `space` | Radical descent below content |
|
|
1082
|
+
| leftSpace | number | `space` | Space left of content |
|
|
1083
|
+
| root | TypeEquationPhrase | | Index content (e.g., '3' for cube root) |
|
|
1084
|
+
| rootOffset | TypeParsablePoint | `[0, 0.06]` | Index offset |
|
|
1085
|
+
| rootScale | number | `0.6` | Index scale |
|
|
1086
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1087
|
+
| useFullBounds | boolean | `false` | Resulting phrase uses full bounds |
|
|
1088
|
+
|
|
1089
|
+
#### EQN_Strike (`strike`)
|
|
1090
|
+
Array: `{ strike: [content, strike_symbol] }`
|
|
1091
|
+
|
|
1092
|
+
| Property | Type | Default | Description |
|
|
1093
|
+
|---|---|---|---|
|
|
1094
|
+
| content | TypeEquationPhrase | | Content to strike through |
|
|
1095
|
+
| symbol | string | | Strike symbol name |
|
|
1096
|
+
| inSize | boolean | `false` | Include strike in size |
|
|
1097
|
+
| space | number | `0.02` | Overhang (all directions) |
|
|
1098
|
+
| topSpace | number | `space` | Top overhang |
|
|
1099
|
+
| rightSpace | number | `space` | Right overhang |
|
|
1100
|
+
| bottomSpace | number | `space` | Bottom overhang |
|
|
1101
|
+
| leftSpace | number | `space` | Left overhang |
|
|
1102
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1103
|
+
| useFullBounds | boolean | `false` | Resulting phrase uses full bounds |
|
|
1104
|
+
|
|
1105
|
+
#### EQN_StrikeComment (`topStrike` / `bottomStrike`)
|
|
1106
|
+
Array: `{ topStrike: [content, symbol, comment] }`
|
|
1107
|
+
|
|
1108
|
+
| Property | Type | Default | Description |
|
|
1109
|
+
|---|---|---|---|
|
|
1110
|
+
| content | TypeEquationPhrase | | Content to strike |
|
|
1111
|
+
| symbol | string | | Strike symbol |
|
|
1112
|
+
| comment | TypeEquationPhrase | | Comment text |
|
|
1113
|
+
| inSize | boolean | `true` | Include in size |
|
|
1114
|
+
| space | number | `0.03` | Strike overhang |
|
|
1115
|
+
| scale | number | `0.6` | Comment scale |
|
|
1116
|
+
| commentSpace | number | `0.03` | Space between strike and comment |
|
|
1117
|
+
|
|
1118
|
+
#### EQN_Box (`box`)
|
|
1119
|
+
Array: `{ box: [content, symbol, inSize, space] }`
|
|
1120
|
+
|
|
1121
|
+
| Property | Type | Default | Description |
|
|
1122
|
+
|---|---|---|---|
|
|
1123
|
+
| content | TypeEquationPhrase | | Content |
|
|
1124
|
+
| symbol | string | | Box symbol |
|
|
1125
|
+
| inSize | boolean | `false` | Include box in size |
|
|
1126
|
+
| space | number | `0` | Space between box and content |
|
|
1127
|
+
| topSpace | number | `space` | Top space |
|
|
1128
|
+
| rightSpace | number | `space` | Right space |
|
|
1129
|
+
| bottomSpace | number | `space` | Bottom space |
|
|
1130
|
+
| leftSpace | number | `space` | Left space |
|
|
1131
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1132
|
+
| useFullBounds | boolean | `false` | Resulting phrase uses full bounds |
|
|
1133
|
+
|
|
1134
|
+
#### EQN_TouchBox (`tBox`)
|
|
1135
|
+
Array: `{ tBox: [content, symbol, space] }`
|
|
1136
|
+
|
|
1137
|
+
| Property | Type | Default | Description |
|
|
1138
|
+
|---|---|---|---|
|
|
1139
|
+
| content | TypeEquationPhrase | | Content |
|
|
1140
|
+
| symbol | string | | Box symbol |
|
|
1141
|
+
| space | number | `0` | Space between box and content |
|
|
1142
|
+
| topSpace | number | `space` | Top space |
|
|
1143
|
+
| rightSpace | number | `space` | Right space |
|
|
1144
|
+
| bottomSpace | number | `space` | Bottom space |
|
|
1145
|
+
| leftSpace | number | `space` | Left space |
|
|
1146
|
+
|
|
1147
|
+
#### EQN_Bar (`bar` / `topBar` / `bottomBar`)
|
|
1148
|
+
Array: `{ bar: [content, symbol, side] }` or `{ topBar: [content, symbol] }`
|
|
1149
|
+
|
|
1150
|
+
| Property | Type | Default | Description |
|
|
1151
|
+
|---|---|---|---|
|
|
1152
|
+
| content | TypeEquationPhrase | | Content |
|
|
1153
|
+
| symbol | string | | Bar/bracket/brace symbol |
|
|
1154
|
+
| inSize | boolean | `true` | Include in size |
|
|
1155
|
+
| space | number | `0.03` | Space between symbol and content |
|
|
1156
|
+
| overhang | number | `0` | Symbol extends beyond content |
|
|
1157
|
+
| length | number | | Total symbol length (overrides overhang) |
|
|
1158
|
+
| left | number | | Left extension (top/bottom only) |
|
|
1159
|
+
| right | number | | Right extension (top/bottom only) |
|
|
1160
|
+
| top | number | | Top extension (left/right only) |
|
|
1161
|
+
| bottom | number | | Bottom extension (left/right only) |
|
|
1162
|
+
| side | `'left'` \| `'right'` \| `'top'` \| `'bottom'` | `'top'` | Symbol position |
|
|
1163
|
+
| minContentHeight | number | | Min content height for sizing |
|
|
1164
|
+
| minContentDescent | number | | Min content descent |
|
|
1165
|
+
| minContentAscent | number | | Min content ascent |
|
|
1166
|
+
| descent | number | | Force descent |
|
|
1167
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1168
|
+
| useFullBounds | boolean | `false` | Resulting phrase uses full bounds |
|
|
1169
|
+
|
|
1170
|
+
#### EQN_Comment (`topComment` / `bottomComment`)
|
|
1171
|
+
Array: `{ topComment: [content, comment, symbol] }`
|
|
1172
|
+
|
|
1173
|
+
| Property | Type | Default | Description |
|
|
1174
|
+
|---|---|---|---|
|
|
1175
|
+
| content | TypeEquationPhrase | | Main content |
|
|
1176
|
+
| comment | TypeEquationPhrase | | Comment content |
|
|
1177
|
+
| symbol | string | | Symbol between content and comment |
|
|
1178
|
+
| contentSpace | number | `0.03` | Space from content to symbol |
|
|
1179
|
+
| commentSpace | number | `0.03` | Space from symbol to comment |
|
|
1180
|
+
| contentLineSpace | number | `0.03` | Space from line symbol to content |
|
|
1181
|
+
| commentLineSpace | number | `0.03` | Space from line symbol to comment |
|
|
1182
|
+
| scale | number | `0.6` | Comment scale |
|
|
1183
|
+
| inSize | boolean | `true` | Include in size |
|
|
1184
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1185
|
+
| useFullBounds | boolean | `false` | Resulting phrase uses full bounds |
|
|
1186
|
+
|
|
1187
|
+
#### EQN_Integral (`int`)
|
|
1188
|
+
Array: `{ int: [symbol, content, from, to] }`
|
|
1189
|
+
|
|
1190
|
+
| Property | Type | Default | Description |
|
|
1191
|
+
|---|---|---|---|
|
|
1192
|
+
| symbol | string | | Integral symbol |
|
|
1193
|
+
| content | TypeEquationPhrase | | Integrand |
|
|
1194
|
+
| from | TypeEquationPhrase | | Lower limit |
|
|
1195
|
+
| to | TypeEquationPhrase | | Upper limit |
|
|
1196
|
+
| inSize | boolean | `true` | Include in size |
|
|
1197
|
+
| space | number | `0.05` | Space between symbol and content |
|
|
1198
|
+
| topSpace | number | `0.1` | Symbol extends above content |
|
|
1199
|
+
| bottomSpace | number | `0.1` | Symbol extends below content |
|
|
1200
|
+
| height | number | | Force symbol height |
|
|
1201
|
+
| yOffset | number | `0` | Symbol y offset |
|
|
1202
|
+
| scale | number | `1` | Content scale |
|
|
1203
|
+
| fromScale | number | `0.5` | Lower limit scale |
|
|
1204
|
+
| toScale | number | `0.5` | Upper limit scale |
|
|
1205
|
+
| fromOffset | TypeParsablePoint | `[0, 0]` | Lower limit offset |
|
|
1206
|
+
| toOffset | TypeParsablePoint | `[0, 0]` | Upper limit offset |
|
|
1207
|
+
| limitsPosition | `'side'` \| `'topBottom'` \| `'topBottomCenter'` | `'side'` | Limits placement |
|
|
1208
|
+
| limitsAroundContent | boolean | | `false` aligns content left of limits |
|
|
1209
|
+
|
|
1210
|
+
#### EQN_SumOf (`sumOf`)
|
|
1211
|
+
Array: `{ sumOf: [symbol, content, from, to] }`
|
|
1212
|
+
|
|
1213
|
+
| Property | Type | Default | Description |
|
|
1214
|
+
|---|---|---|---|
|
|
1215
|
+
| symbol | string | | Sum symbol |
|
|
1216
|
+
| content | TypeEquationPhrase | | Content |
|
|
1217
|
+
| from | TypeEquationPhrase | | Lower limit |
|
|
1218
|
+
| to | TypeEquationPhrase | | Upper limit |
|
|
1219
|
+
| inSize | boolean | `true` | Include in size |
|
|
1220
|
+
| space | number | `0.1` | Space between symbol and content |
|
|
1221
|
+
| topSpace | number | `0.07` | Symbol extends above content |
|
|
1222
|
+
| bottomSpace | number | `0.07` | Symbol extends below content |
|
|
1223
|
+
| height | number | | Force symbol height |
|
|
1224
|
+
| yOffset | number | `0` | Symbol y offset |
|
|
1225
|
+
| scale | number | `1` | Content scale |
|
|
1226
|
+
| fromScale | number | `0.5` | Lower limit scale |
|
|
1227
|
+
| toScale | number | `0.5` | Upper limit scale |
|
|
1228
|
+
| fromSpace | number | `0.04` | Space between symbol and from |
|
|
1229
|
+
| toSpace | number | `0.04` | Space between symbol and to |
|
|
1230
|
+
| fromOffset | TypeParsablePoint | `[0, 0]` | Lower limit offset |
|
|
1231
|
+
| toOffset | TypeParsablePoint | `[0, 0]` | Upper limit offset |
|
|
1232
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1233
|
+
|
|
1234
|
+
#### EQN_ProdOf (`prodOf`)
|
|
1235
|
+
Same properties as EQN_SumOf. Uses `prod` symbol instead.
|
|
1236
|
+
|
|
1237
|
+
#### EQN_Scale (`scale`)
|
|
1238
|
+
Array: `{ scale: [content, scale_factor] }`
|
|
1239
|
+
|
|
1240
|
+
| Property | Type | Default | Description |
|
|
1241
|
+
|---|---|---|---|
|
|
1242
|
+
| content | TypeEquationPhrase | | Content |
|
|
1243
|
+
| scale | number | `1` | Scale factor |
|
|
1244
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1245
|
+
|
|
1246
|
+
#### EQN_Color (`color`)
|
|
1247
|
+
Array: `{ color: [content, [r, g, b, a]] }`
|
|
1248
|
+
|
|
1249
|
+
| Property | Type | Default | Description |
|
|
1250
|
+
|---|---|---|---|
|
|
1251
|
+
| content | TypeEquationPhrase | | Content |
|
|
1252
|
+
| color | TypeColor | | Color to apply |
|
|
1253
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1254
|
+
|
|
1255
|
+
#### EQN_Container (`container`)
|
|
1256
|
+
Array: `{ container: [content, width] }`
|
|
1257
|
+
|
|
1258
|
+
| Property | Type | Default | Description |
|
|
1259
|
+
|---|---|---|---|
|
|
1260
|
+
| content | TypeEquationPhrase | | Content |
|
|
1261
|
+
| width | number \| null | `null` | Fixed width |
|
|
1262
|
+
| inSize | boolean | `true` | Include in size |
|
|
1263
|
+
| descent | number \| null | `null` | Fixed descent |
|
|
1264
|
+
| ascent | number \| null | `null` | Fixed ascent |
|
|
1265
|
+
| xAlign | `'left'` \| `'center'` \| `'right'` \| number | `'center'` | Content x alignment |
|
|
1266
|
+
| yAlign | `'bottom'` \| `'middle'` \| `'top'` \| `'baseline'` \| number | `'baseline'` | Content y alignment |
|
|
1267
|
+
| fit | `'width'` \| `'height'` \| `'contain'` \| null | `null` | Auto-fit mode |
|
|
1268
|
+
| scale | number | `1` | Content scale |
|
|
1269
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1270
|
+
| showContent | boolean | `true` | `false` creates invisible container |
|
|
1271
|
+
|
|
1272
|
+
#### EQN_Offset (`offset`)
|
|
1273
|
+
Array: `{ offset: [content, [x, y]] }`
|
|
1274
|
+
|
|
1275
|
+
| Property | Type | Default | Description |
|
|
1276
|
+
|---|---|---|---|
|
|
1277
|
+
| content | TypeEquationPhrase | | Content |
|
|
1278
|
+
| offset | TypeParsablePoint | `[0, 0]` | Offset amount |
|
|
1279
|
+
| inSize | boolean | `true` | Include in size |
|
|
1280
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1281
|
+
|
|
1282
|
+
#### EQN_Pad (`pad`)
|
|
1283
|
+
Array: `{ pad: [content, top, right, bottom, left] }`
|
|
1284
|
+
|
|
1285
|
+
| Property | Type | Default | Description |
|
|
1286
|
+
|---|---|---|---|
|
|
1287
|
+
| content | TypeEquationPhrase | | Content |
|
|
1288
|
+
| top | number | `0` | Top padding |
|
|
1289
|
+
| right | number | `0` | Right padding |
|
|
1290
|
+
| bottom | number | `0` | Bottom padding |
|
|
1291
|
+
| left | number | `0` | Left padding |
|
|
1292
|
+
|
|
1293
|
+
#### EQN_Matrix (`matrix`)
|
|
1294
|
+
Array: `{ matrix: [order, left, content, right] }`
|
|
1295
|
+
|
|
1296
|
+
| Property | Type | Default | Description |
|
|
1297
|
+
|---|---|---|---|
|
|
1298
|
+
| order | [rows, cols] | `[1, content.length]` | Matrix dimensions |
|
|
1299
|
+
| left | string | | Left bracket symbol |
|
|
1300
|
+
| content | TypeEquationPhrase[] | | Matrix elements (flat array) |
|
|
1301
|
+
| right | string | | Right bracket symbol |
|
|
1302
|
+
| scale | number | `0.7` | Element scale |
|
|
1303
|
+
| fit | `'max'` \| `'min'` \| TypeParsablePoint | `'min'` | Cell sizing mode |
|
|
1304
|
+
| space | TypeParsablePoint | `[0.05, 0.05]` | Cell spacing |
|
|
1305
|
+
| yAlign | `'baseline'` \| `'middle'` | `'baseline'` | Row alignment |
|
|
1306
|
+
| brac | EQN_Bracket | | Bracket options |
|
|
1307
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1308
|
+
|
|
1309
|
+
#### EQN_Lines (`lines`)
|
|
1310
|
+
|
|
1311
|
+
| Property | Type | Default | Description |
|
|
1312
|
+
|---|---|---|---|
|
|
1313
|
+
| content | (TypeEquationPhrase \| EQN_Line)[] | | Array of lines |
|
|
1314
|
+
| justify | `'left'` \| `'center'` \| `'right'` \| `'element'` | `'left'` | Line alignment |
|
|
1315
|
+
| baselineSpace | number \| null | `null` | Space between baselines (overrides space) |
|
|
1316
|
+
| space | number | `0` | Space between descent and ascent |
|
|
1317
|
+
| yAlign | `'bottom'` \| `'middle'` \| `'top'` \| number | `0` | Vertical alignment (number = line index baseline) |
|
|
1318
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1319
|
+
|
|
1320
|
+
EQN_Line (individual line in `lines`):
|
|
1321
|
+
|
|
1322
|
+
| Property | Type | Default | Description |
|
|
1323
|
+
|---|---|---|---|
|
|
1324
|
+
| content | TypeEquationPhrase | | Line content |
|
|
1325
|
+
| justify | string | | Element name for `'element'` justify mode |
|
|
1326
|
+
| space | number | `0` | Override spacing for this line |
|
|
1327
|
+
| baselineSpace | number \| null | `null` | Override baseline space for this line |
|
|
1328
|
+
| offset | number | `0` | X offset from justification position |
|
|
1329
|
+
|
|
1330
|
+
#### EQN_Annotate (`annotate`)
|
|
1331
|
+
Object only (no array syntax).
|
|
1332
|
+
|
|
1333
|
+
| Property | Type | Default | Description |
|
|
1334
|
+
|---|---|---|---|
|
|
1335
|
+
| content | TypeEquationPhrase | | Main content |
|
|
1336
|
+
| annotation | EQN_Annotation | | Single annotation |
|
|
1337
|
+
| annotations | EQN_Annotation[] | | Multiple annotations |
|
|
1338
|
+
| glyphs | EQN_Glyphs | | Glyph annotations (encompass, top, bottom, left, right, line) |
|
|
1339
|
+
| inSize | boolean | `true` | Include annotations in size |
|
|
1340
|
+
| space | number | `0` | Extend size on all sides |
|
|
1341
|
+
| topSpace | number | | Top size extension |
|
|
1342
|
+
| bottomSpace | number | | Bottom size extension |
|
|
1343
|
+
| leftSpace | number | | Left size extension |
|
|
1344
|
+
| rightSpace | number | | Right size extension |
|
|
1345
|
+
| contentScale | number | `1` | Content scale |
|
|
1346
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1347
|
+
| useFullBounds | boolean | `false` | Resulting phrase uses full bounds |
|
|
1348
|
+
|
|
1349
|
+
EQN_Annotation (annotation positioning):
|
|
1350
|
+
|
|
1351
|
+
| Property | Type | Default | Description |
|
|
1352
|
+
|---|---|---|---|
|
|
1353
|
+
| content | TypeEquationPhrase | | Annotation content |
|
|
1354
|
+
| xPosition | `'left'` \| `'center'` \| `'right'` \| number | `'center'` | Position relative to content |
|
|
1355
|
+
| yPosition | `'bottom'` \| `'baseline'` \| `'middle'` \| `'top'` \| number | `'top'` | Position relative to content |
|
|
1356
|
+
| xAlign | `'left'` \| `'center'` \| `'right'` \| number | `'center'` | Annotation alignment |
|
|
1357
|
+
| yAlign | `'bottom'` \| `'baseline'` \| `'middle'` \| `'top'` \| number | `'bottom'` | Annotation alignment |
|
|
1358
|
+
| offset | TypeParsablePoint | `[0, 0]` | Annotation offset |
|
|
1359
|
+
| scale | number | `1` | Annotation scale |
|
|
1360
|
+
| inSize | boolean | `true` | Include in phrase size |
|
|
1361
|
+
| fullContentBounds | boolean | `false` | Use full bounds |
|
|
1362
|
+
|
|
1363
|
+
EQN_Glyphs (glyph positions in `annotate`):
|
|
1364
|
+
|
|
1365
|
+
| Property | Type | Description |
|
|
1366
|
+
|---|---|---|
|
|
1367
|
+
| encompass | EQN_EncompassGlyph | Glyph surrounding content |
|
|
1368
|
+
| top | EQN_TopBottomGlyph | Glyph above content |
|
|
1369
|
+
| bottom | EQN_TopBottomGlyph | Glyph below content |
|
|
1370
|
+
| left | EQN_LeftRightGlyph | Glyph left of content |
|
|
1371
|
+
| right | EQN_LeftRightGlyph | Glyph right of content |
|
|
1372
|
+
| line | EQN_LineGlyph | Line glyph connecting content to annotation |
|
|
1373
|
+
|
|
1374
|
+
### Annotate Glyph Sub-types
|
|
1375
|
+
|
|
1376
|
+
#### EQN_EncompassGlyph (surrounds content)
|
|
1377
|
+
|
|
1378
|
+
| Property | Type | Default | Description |
|
|
1379
|
+
|---|---|---|---|
|
|
1380
|
+
| symbol | string | | Glyph symbol name |
|
|
1381
|
+
| annotation | EQN_Annotation | | Single annotation |
|
|
1382
|
+
| annotations | EQN_Annotation[] | | Multiple annotations |
|
|
1383
|
+
| space | number | `0` | Space glyph extends beyond content (all sides) |
|
|
1384
|
+
| topSpace | number | | Override top space |
|
|
1385
|
+
| rightSpace | number | | Override right space |
|
|
1386
|
+
| bottomSpace | number | | Override bottom space |
|
|
1387
|
+
| leftSpace | number | | Override left space |
|
|
1388
|
+
|
|
1389
|
+
#### EQN_LeftRightGlyph (left or right of content)
|
|
1390
|
+
|
|
1391
|
+
| Property | Type | Default | Description |
|
|
1392
|
+
|---|---|---|---|
|
|
1393
|
+
| symbol | string | | Glyph symbol name |
|
|
1394
|
+
| annotation | EQN_Annotation | | Single annotation |
|
|
1395
|
+
| annotations | EQN_Annotation[] | | Multiple annotations |
|
|
1396
|
+
| space | number | `0` | Horizontal space between glyph and content |
|
|
1397
|
+
| overhang | number | `0` | Glyph extends above/below content |
|
|
1398
|
+
| topSpace | number | | Override top overhang |
|
|
1399
|
+
| bottomSpace | number | | Override bottom overhang |
|
|
1400
|
+
| minContentHeight | number | | Min content height for auto sizing |
|
|
1401
|
+
| minContentDescent | number | | Min content descent for auto sizing |
|
|
1402
|
+
| minContentAscent | number | | Min content ascent for auto sizing |
|
|
1403
|
+
| descent | number | | Force glyph descent |
|
|
1404
|
+
| height | number | | Force glyph height |
|
|
1405
|
+
| yOffset | number | `0` | Y offset of glyph |
|
|
1406
|
+
| annotationsOverContent | boolean | `false` | Only glyph (not annotations) separated by space |
|
|
1407
|
+
|
|
1408
|
+
#### EQN_TopBottomGlyph (above or below content)
|
|
1409
|
+
|
|
1410
|
+
| Property | Type | Default | Description |
|
|
1411
|
+
|---|---|---|---|
|
|
1412
|
+
| symbol | string | | Glyph symbol name |
|
|
1413
|
+
| annotation | EQN_Annotation | | Single annotation |
|
|
1414
|
+
| annotations | EQN_Annotation[] | | Multiple annotations |
|
|
1415
|
+
| space | number | `0` | Vertical space between glyph and content |
|
|
1416
|
+
| overhang | number | `0` | Glyph extends left/right of content |
|
|
1417
|
+
| width | number | | Force glyph width |
|
|
1418
|
+
| leftSpace | number | | Glyph extends beyond content left |
|
|
1419
|
+
| rightSpace | number | | Glyph extends beyond content right |
|
|
1420
|
+
| xOffset | number | `0` | X offset of glyph |
|
|
1421
|
+
| annotationsOverContent | boolean | `false` | Only glyph (not annotations) separated by space |
|
|
1422
|
+
|
|
1423
|
+
#### EQN_LineGlyph (line connecting content to annotation)
|
|
1424
|
+
|
|
1425
|
+
| Property | Type | Default | Description |
|
|
1426
|
+
|---|---|---|---|
|
|
1427
|
+
| symbol | string | | Line symbol name |
|
|
1428
|
+
| content | object | | Content endpoint alignment: `{ xAlign, yAlign, space }` |
|
|
1429
|
+
| annotation | object | | Annotation endpoint alignment: `{ xAlign, yAlign, space }` |
|
|
1430
|
+
| annotationIndex | number | | Which annotation to draw line to |
|
|
1431
|
+
|
|
1432
|
+
### Form Object Options
|
|
1433
|
+
|
|
1434
|
+
When defining a form as an object (instead of just a content array), additional options control alignment and animation:
|
|
1435
|
+
|
|
1436
|
+
```js
|
|
1437
|
+
forms: {
|
|
1438
|
+
formName: {
|
|
1439
|
+
content: [...], // Equation phrase
|
|
1440
|
+
alignment: {
|
|
1441
|
+
fixTo: 'elementName', // Fix alignment to this element
|
|
1442
|
+
xAlign: 'center', // 'left'|'center'|'right'|number
|
|
1443
|
+
yAlign: 'baseline', // 'bottom'|'baseline'|'middle'|'top'|number
|
|
1444
|
+
},
|
|
1445
|
+
translation: { // Per-element animation paths
|
|
1446
|
+
elementName: {
|
|
1447
|
+
style: 'curved', // 'linear'|'curved'
|
|
1448
|
+
direction: 'up', // 'up'|'down'|'left'|'right'
|
|
1449
|
+
mag: 0.5, // Curve magnitude
|
|
1450
|
+
},
|
|
1451
|
+
},
|
|
1452
|
+
scale: { elementName: 1.5 }, // Per-element target scales during animation
|
|
1453
|
+
fromPrev: { elementName: 'otherElement' }, // Animate from another element's position
|
|
1454
|
+
fromNext: { elementName: 'otherElement' }, // Animate from another element's position (reverse)
|
|
1455
|
+
},
|
|
1456
|
+
}
|
|
1457
|
+
```
|
|
1458
|
+
|
|
1459
|
+
### Forms and Animation
|
|
1460
|
+
|
|
1461
|
+
```js
|
|
1462
|
+
const eqn = figure.add({
|
|
1463
|
+
make: 'equation',
|
|
1464
|
+
elements: { v: { symbol: 'vinculum' }, equals: ' = ', times: ' × ' },
|
|
1465
|
+
formDefaults: { alignment: { fixTo: 'equals' } },
|
|
1466
|
+
forms: {
|
|
1467
|
+
1: ['a', 'equals', { frac: ['b', 'v', 'c'] }],
|
|
1468
|
+
2: {
|
|
1469
|
+
content: ['c', 'times', 'a', 'equals', 'b'],
|
|
1470
|
+
translation: { c: { style: 'curved', direction: 'down', mag: 0.5 } },
|
|
1471
|
+
},
|
|
1472
|
+
},
|
|
1473
|
+
formSeries: { default: ['1', '2'] },
|
|
1474
|
+
});
|
|
1475
|
+
|
|
1476
|
+
eqn.showForm('1');
|
|
1477
|
+
eqn.goToForm({ form: '2', delay: 1, duration: 1.5, animate: 'move' });
|
|
1478
|
+
eqn.nextForm(); // Navigate formSeries
|
|
1479
|
+
eqn.prevForm();
|
|
1480
|
+
```
|
|
1481
|
+
|
|
1482
|
+
### Phrases (reusable sub-expressions)
|
|
1483
|
+
```js
|
|
1484
|
+
{
|
|
1485
|
+
make: 'equation',
|
|
1486
|
+
phrases: { Csq: { sup: ['C', '2'] } },
|
|
1487
|
+
forms: { 1: ['a', '_ = ', 'Csq'] },
|
|
1488
|
+
}
|
|
1489
|
+
```
|
|
1490
|
+
|
|
1491
|
+
---
|
|
1492
|
+
|
|
1493
|
+
## 7. Animation System
|
|
1494
|
+
|
|
1495
|
+
Animations use a builder chain on `element.animations`.
|
|
1496
|
+
|
|
1497
|
+
### AnimationBuilder Methods
|
|
1498
|
+
|
|
1499
|
+
```js
|
|
1500
|
+
element.animations.new()
|
|
1501
|
+
.position(target_or_options)
|
|
1502
|
+
.rotation(target_or_options)
|
|
1503
|
+
.scale(target_or_options)
|
|
1504
|
+
.transform(target_or_options)
|
|
1505
|
+
.color(target_or_options)
|
|
1506
|
+
.opacity(target_or_options)
|
|
1507
|
+
.dissolveIn(duration?)
|
|
1508
|
+
.dissolveOut(duration?)
|
|
1509
|
+
.dim(options?)
|
|
1510
|
+
.undim(options?)
|
|
1511
|
+
.pulse(scale_or_options)
|
|
1512
|
+
.scenario(options)
|
|
1513
|
+
.scenarios(options)
|
|
1514
|
+
.delay(duration)
|
|
1515
|
+
.trigger(callback_or_options)
|
|
1516
|
+
.custom(callback_or_options)
|
|
1517
|
+
.inParallel([steps])
|
|
1518
|
+
.whenFinished(callback)
|
|
1519
|
+
.start();
|
|
1520
|
+
```
|
|
1521
|
+
|
|
1522
|
+
Steps are sequential by default. Use `.inParallel([...])` for simultaneous.
|
|
1523
|
+
|
|
1524
|
+
### OBJ_AnimationStep (base)
|
|
1525
|
+
|
|
1526
|
+
| Property | Type | Default | Description |
|
|
1527
|
+
|---|---|---|---|
|
|
1528
|
+
| duration | number | `0` | Duration in seconds |
|
|
1529
|
+
| delay | number | `0` | Delay before start |
|
|
1530
|
+
| name | string | random | Animation name |
|
|
1531
|
+
| onFinish | function \| null | null | Completion callback |
|
|
1532
|
+
| completeOnCancel | boolean \| null | null | Skip to end on cancel |
|
|
1533
|
+
| precision | number | `8` | Calculation precision |
|
|
1534
|
+
|
|
1535
|
+
### OBJ_ElementAnimationStep (extends OBJ_AnimationStep)
|
|
1536
|
+
|
|
1537
|
+
| Property | Type | Default | Description |
|
|
1538
|
+
|---|---|---|---|
|
|
1539
|
+
| element | FigureElement | | Target element |
|
|
1540
|
+
| progression | string \| function | `'easeinout'` | `'linear'`, `'easeinout'`, `'easein'`, `'easeout'`, or custom function |
|
|
1541
|
+
|
|
1542
|
+
### OBJ_PositionAnimationStep
|
|
1543
|
+
|
|
1544
|
+
| Property | Type | Default | Description |
|
|
1545
|
+
|---|---|---|---|
|
|
1546
|
+
| start | Point | current | Start position |
|
|
1547
|
+
| target | Point | | Target position |
|
|
1548
|
+
| delta | Point | | Delta (if no target) |
|
|
1549
|
+
| velocity | Point \| null | null | Velocity (overrides duration) |
|
|
1550
|
+
| path | OBJ_TranslationPath | `{ style: 'linear' }` | Path style |
|
|
1551
|
+
| maxDuration | number \| null | null | Duration cap |
|
|
1552
|
+
|
|
1553
|
+
### OBJ_RotationAnimationStep
|
|
1554
|
+
|
|
1555
|
+
| Property | Type | Default | Description |
|
|
1556
|
+
|---|---|---|---|
|
|
1557
|
+
| start | number | current | Start angle |
|
|
1558
|
+
| target | number | | Target angle |
|
|
1559
|
+
| delta | number | | Delta (if no target) |
|
|
1560
|
+
| velocity | number \| null | null | Velocity (rad/s) |
|
|
1561
|
+
| direction | `0` \| `1` \| `-1` \| `2` | `0` | 0=quickest, 1=CCW, -1=CW, 2=avoid 0 |
|
|
1562
|
+
|
|
1563
|
+
### OBJ_ScaleAnimationStep
|
|
1564
|
+
|
|
1565
|
+
| Property | Type | Default | Description |
|
|
1566
|
+
|---|---|---|---|
|
|
1567
|
+
| start | Point \| number | current | Start scale |
|
|
1568
|
+
| target | Point \| number | | Target scale |
|
|
1569
|
+
| delta | Point \| number | | Delta (if no target) |
|
|
1570
|
+
|
|
1571
|
+
### OBJ_TransformAnimationStep
|
|
1572
|
+
|
|
1573
|
+
| Property | Type | Default | Description |
|
|
1574
|
+
|---|---|---|---|
|
|
1575
|
+
| start | Transform | current | Start transform |
|
|
1576
|
+
| target | Transform | | Target transform |
|
|
1577
|
+
| path | OBJ_TranslationPath | `{ style: 'linear' }` | Translation path |
|
|
1578
|
+
| rotDirection | `0` \| `1` \| `-1` \| `2` | `0` | Rotation direction |
|
|
1579
|
+
| clipRotationTo | `'0to360'` \| `'-180to180'` \| null | null | Clip rotation |
|
|
1580
|
+
|
|
1581
|
+
### OBJ_ColorAnimationStep
|
|
1582
|
+
|
|
1583
|
+
| Property | Type | Default | Description |
|
|
1584
|
+
|---|---|---|---|
|
|
1585
|
+
| start | TypeColor | current | Start color |
|
|
1586
|
+
| target | TypeColor \| `'dim'` \| `'undim'` | | Target color |
|
|
1587
|
+
| dissolve | `'in'` \| `'out'` \| null | null | Dissolve mode |
|
|
1588
|
+
|
|
1589
|
+
### OBJ_OpacityAnimationStep
|
|
1590
|
+
|
|
1591
|
+
| Property | Type | Default | Description |
|
|
1592
|
+
|---|---|---|---|
|
|
1593
|
+
| start | number | current | Start opacity |
|
|
1594
|
+
| target | number | | Target opacity |
|
|
1595
|
+
| dissolve | `'in'` \| `'out'` \| null | null | Dissolve mode |
|
|
1596
|
+
|
|
1597
|
+
### OBJ_CustomAnimationStep
|
|
1598
|
+
|
|
1599
|
+
| Property | Type | Default | Description |
|
|
1600
|
+
|---|---|---|---|
|
|
1601
|
+
| callback | function | | Called each frame with percent (0-1) |
|
|
1602
|
+
| duration | number \| null | | null = infinite |
|
|
1603
|
+
| progression | string \| function | `'linear'` | Progression function |
|
|
1604
|
+
|
|
1605
|
+
### OBJ_TriggerAnimationStep
|
|
1606
|
+
|
|
1607
|
+
| Property | Type | Default | Description |
|
|
1608
|
+
|---|---|---|---|
|
|
1609
|
+
| callback | function | | Function to execute |
|
|
1610
|
+
| payload | any | null | Argument to callback |
|
|
1611
|
+
|
|
1612
|
+
### OBJ_ScenarioAnimationStep
|
|
1613
|
+
|
|
1614
|
+
| Property | Type | Default | Description |
|
|
1615
|
+
|---|---|---|---|
|
|
1616
|
+
| start | string \| OBJ_Scenario | current | Start scenario |
|
|
1617
|
+
| target | string \| OBJ_Scenario | | Target scenario |
|
|
1618
|
+
| velocity | OBJ_ScenarioVelocity | null | Velocity (overrides duration) |
|
|
1619
|
+
| path | OBJ_TranslationPath | `{ style: 'linear' }` | Translation path |
|
|
1620
|
+
| rotDirection | `0` \| `1` \| `-1` \| `2` | `0` | Rotation direction |
|
|
1621
|
+
|
|
1622
|
+
### OBJ_PulseAnimationStep
|
|
1623
|
+
|
|
1624
|
+
| Property | Type | Default | Description |
|
|
1625
|
+
|---|---|---|---|
|
|
1626
|
+
| scale | number | `1.5` | Max pulse scale |
|
|
1627
|
+
| frequency | number | `0` | Hz (0 = one cycle) |
|
|
1628
|
+
| rotation | number | | Max rotation |
|
|
1629
|
+
| centerOn | FigureElement \| Point \| null | element center | Pulse center |
|
|
1630
|
+
| xAlign | `'left'` \| `'center'` \| `'right'` \| `'origin'` | `'center'` | X alignment |
|
|
1631
|
+
| yAlign | `'bottom'` \| `'middle'` \| `'top'` \| `'origin'` | `'center'` | Y alignment |
|
|
1632
|
+
| num | number | `1` | Draw copies |
|
|
1633
|
+
|
|
1634
|
+
### OBJ_TranslationPath
|
|
1635
|
+
|
|
1636
|
+
| Property | Type | Default | Description |
|
|
1637
|
+
|---|---|---|---|
|
|
1638
|
+
| style | `'linear'` \| `'curve'` | `'linear'` | Path style |
|
|
1639
|
+
| magnitude | number | | Curve magnitude |
|
|
1640
|
+
| offset | number | | Point on line (0.5=mid) |
|
|
1641
|
+
| angle | number | `π/2` | Control point angle |
|
|
1642
|
+
| direction | `'positive'` \| `'negative'` \| `'up'` \| `'down'` \| `'left'` \| `'right'` | | Curve side |
|
|
1643
|
+
| controlPoint | Point \| null | null | Direct bezier control point |
|
|
1644
|
+
|
|
1645
|
+
```js
|
|
1646
|
+
// Animation examples
|
|
1647
|
+
const sq = figure.add({ make: 'rectangle', width: 0.4, height: 0.4, color: [1, 0, 0, 1] });
|
|
1648
|
+
|
|
1649
|
+
// Sequential chain
|
|
1650
|
+
sq.animations.new()
|
|
1651
|
+
.position({ target: [0.5, 0], duration: 1 })
|
|
1652
|
+
.rotation({ target: Math.PI / 4, duration: 0.5 })
|
|
1653
|
+
.dissolveOut(0.5)
|
|
1654
|
+
.start();
|
|
1655
|
+
|
|
1656
|
+
// Parallel
|
|
1657
|
+
sq.animations.new()
|
|
1658
|
+
.inParallel([
|
|
1659
|
+
sq.animations.position({ target: [0.5, 0], duration: 1 }),
|
|
1660
|
+
sq.animations.rotation({ target: Math.PI, duration: 1 }),
|
|
1661
|
+
])
|
|
1662
|
+
.start();
|
|
1663
|
+
|
|
1664
|
+
// Curved path
|
|
1665
|
+
sq.animations.new()
|
|
1666
|
+
.position({ target: [0.5, 0.5], duration: 2, path: { style: 'curve', direction: 'up', magnitude: 0.5 } })
|
|
1667
|
+
.start();
|
|
1668
|
+
```
|
|
1669
|
+
|
|
1670
|
+
---
|
|
1671
|
+
|
|
1672
|
+
## 8. Interactivity
|
|
1673
|
+
|
|
1674
|
+
### OBJ_Touch
|
|
1675
|
+
|
|
1676
|
+
| Property | Type | Default | Description |
|
|
1677
|
+
|---|---|---|---|
|
|
1678
|
+
| enable | boolean | `true` | Enable touch |
|
|
1679
|
+
| onClick | function \| string | | Touch callback |
|
|
1680
|
+
|
|
1681
|
+
### OBJ_ElementMove
|
|
1682
|
+
|
|
1683
|
+
| Property | Type | Default | Description |
|
|
1684
|
+
|---|---|---|---|
|
|
1685
|
+
| type | `'translation'` \| `'rotation'` \| `'position'` \| `'scale'` \| `'scaleX'` \| `'scaleY'` \| `'scaleZ'` | `'translation'` | Move type |
|
|
1686
|
+
| bounds | TypeParsableBounds | | Movement bounds rectangle |
|
|
1687
|
+
| plane | Plane | | Movement plane (3D) |
|
|
1688
|
+
| maxVelocity | number \| TypeParsablePoint | `5` | Maximum velocity |
|
|
1689
|
+
| freely | OBJ_ElementMoveFreely \| false | | Free movement with deceleration (false to disable) |
|
|
1690
|
+
| element | FigureElement \| string \| null | | Element to move (default: self) |
|
|
1691
|
+
|
|
1692
|
+
### OBJ_ElementMoveFreely
|
|
1693
|
+
|
|
1694
|
+
| Property | Type | Default | Description |
|
|
1695
|
+
|---|---|---|---|
|
|
1696
|
+
| deceleration | number | | Deceleration (local units/s²) |
|
|
1697
|
+
| bounceLoss | number | | Velocity loss on bounce (0.5 = 50% loss) |
|
|
1698
|
+
| zeroVelocityThreshold | number | | Threshold to stop movement |
|
|
1699
|
+
| callback | function \| string \| null | | Called each frame of free movement |
|
|
1700
|
+
|
|
1701
|
+
### OBJ_Pulse
|
|
1702
|
+
|
|
1703
|
+
| Property | Type | Default | Description |
|
|
1704
|
+
|---|---|---|---|
|
|
1705
|
+
| scale | number | `1.5` | Max pulse scale |
|
|
1706
|
+
| duration | number | `1` | Duration in seconds |
|
|
1707
|
+
| frequency | number | `0` | Hz (0 = one cycle) |
|
|
1708
|
+
| rotation | number | | Max rotation angle |
|
|
1709
|
+
| xAlign | `'left'` \| `'center'` \| `'right'` \| `'origin'` | `'center'` | X alignment |
|
|
1710
|
+
| yAlign | `'bottom'` \| `'middle'` \| `'top'` \| `'origin'` | `'middle'` | Y alignment |
|
|
1711
|
+
| space | `'figure'` \| `'gl'` \| `'local'` \| `'draw'` | `'figure'` | Coordinate space |
|
|
1712
|
+
| num | number | `1` | Number of copies to draw |
|
|
1713
|
+
| when | TypeWhen | `'syncNow'` | When to start pulse |
|
|
1714
|
+
| done | function \| string \| null | `null` | Completion callback |
|
|
1715
|
+
| progression | string \| function | `'sinusoid'` | Progress function |
|
|
1716
|
+
|
|
1717
|
+
### Making elements interactive
|
|
1718
|
+
|
|
1719
|
+
```js
|
|
1720
|
+
// Movable with bounds
|
|
1721
|
+
figure.add({
|
|
1722
|
+
make: 'polygon', sides: 100, radius: 0.2,
|
|
1723
|
+
move: {
|
|
1724
|
+
type: 'translation',
|
|
1725
|
+
bounds: { left: -0.8, bottom: -0.8, right: 0.8, top: 0.8 },
|
|
1726
|
+
freely: { deceleration: 0.5 },
|
|
1727
|
+
},
|
|
1728
|
+
});
|
|
1729
|
+
|
|
1730
|
+
// Rotatable
|
|
1731
|
+
figure.add({
|
|
1732
|
+
make: 'polygon', sides: 6, radius: 0.3,
|
|
1733
|
+
move: { type: 'rotation' },
|
|
1734
|
+
});
|
|
1735
|
+
|
|
1736
|
+
// Touchable with callback
|
|
1737
|
+
element.setTouchable();
|
|
1738
|
+
element.onClick = () => { /* handle */ };
|
|
1739
|
+
|
|
1740
|
+
// Or via mods
|
|
1741
|
+
figure.add({
|
|
1742
|
+
make: 'polygon', radius: 0.3, sides: 4,
|
|
1743
|
+
mods: { isTouchable: true, touchBorder: 0.1 },
|
|
1744
|
+
});
|
|
1745
|
+
```
|
|
1746
|
+
|
|
1747
|
+
### Notifications
|
|
1748
|
+
|
|
1749
|
+
```js
|
|
1750
|
+
element.notifications.add('setTransform', () => {
|
|
1751
|
+
const p = element.getPosition().round(1);
|
|
1752
|
+
text.setText({ text: `(${p.x.toFixed(1)}, ${p.y.toFixed(1)})` });
|
|
1753
|
+
});
|
|
1754
|
+
element.notifications.add('onClick', () => { /* ... */ });
|
|
1755
|
+
// Common: 'setTransform', 'onClick', 'animationsFinished', 'setFigure'
|
|
1756
|
+
```
|
|
1757
|
+
|
|
1758
|
+
---
|
|
1759
|
+
|
|
1760
|
+
## 9. Scenarios
|
|
1761
|
+
|
|
1762
|
+
Named presets for position, rotation, scale, and color.
|
|
1763
|
+
|
|
1764
|
+
### OBJ_Scenario
|
|
1765
|
+
|
|
1766
|
+
| Property | Type | Description |
|
|
1767
|
+
|---|---|---|
|
|
1768
|
+
| position | TypeParsablePoint | Position |
|
|
1769
|
+
| rotation | number | Rotation |
|
|
1770
|
+
| scale | TypeParsablePoint \| number | Scale |
|
|
1771
|
+
| color | TypeColor | Color |
|
|
1772
|
+
| transform | TypeParsableTransform | Full transform |
|
|
1773
|
+
| isShown | boolean | Visibility |
|
|
1774
|
+
|
|
1775
|
+
```js
|
|
1776
|
+
figure.add({
|
|
1777
|
+
name: 'shape', make: 'polygon', sides: 4, radius: 0.3,
|
|
1778
|
+
mods: {
|
|
1779
|
+
scenarios: {
|
|
1780
|
+
center: { position: [0, 0], scale: 1, color: [1, 0, 0, 1] },
|
|
1781
|
+
right: { position: [1, 0], scale: 2, color: [0, 0, 1, 1] },
|
|
1782
|
+
},
|
|
1783
|
+
},
|
|
1784
|
+
});
|
|
1785
|
+
|
|
1786
|
+
// Set instantly
|
|
1787
|
+
figure.elements._shape.setScenario('center');
|
|
1788
|
+
|
|
1789
|
+
// Animate to scenario
|
|
1790
|
+
figure.elements._shape.animations.new()
|
|
1791
|
+
.scenario({ target: 'right', duration: 1 })
|
|
1792
|
+
.start();
|
|
1793
|
+
|
|
1794
|
+
// Set all children
|
|
1795
|
+
figure.elements.setScenarios('center');
|
|
1796
|
+
```
|
|
1797
|
+
|
|
1798
|
+
---
|
|
1799
|
+
|
|
1800
|
+
## 10. SlideNavigator
|
|
1801
|
+
|
|
1802
|
+
Manages sequential presentation states with animated transitions.
|
|
1803
|
+
|
|
1804
|
+
### COL_SlideNavigator (`make: 'collections.slideNavigator'`)
|
|
1805
|
+
|
|
1806
|
+
| Property | Type | Default | Description |
|
|
1807
|
+
|---|---|---|---|
|
|
1808
|
+
| collection | Figure \| FigureElementCollection | parent | Collection to manage |
|
|
1809
|
+
| slides | OBJ_SlideNavigatorSlide[] | | Slide definitions |
|
|
1810
|
+
| prevButton | object \| null | | Previous button |
|
|
1811
|
+
| nextButton | object \| null | | Next button |
|
|
1812
|
+
| text | OBJ_FormattedText \| null | | Text element |
|
|
1813
|
+
| equation | Equation \| string \| string[] | | Equation(s) |
|
|
1814
|
+
| equationDefaults | object | | Default equation animation |
|
|
1815
|
+
| disableOpacity | number | `0.7` | Disabled button opacity |
|
|
1816
|
+
|
|
1817
|
+
### OBJ_SlideNavigatorSlide
|
|
1818
|
+
|
|
1819
|
+
| Property | Type | Description |
|
|
1820
|
+
|---|---|---|
|
|
1821
|
+
| show | TypeElementPath | Elements to show |
|
|
1822
|
+
| showCommon | TypeElementPath | Common elements to show (persists to subsequent slides) |
|
|
1823
|
+
| hide | TypeElementPath | Elements to hide |
|
|
1824
|
+
| hideCommon | TypeElementPath | Common elements to hide |
|
|
1825
|
+
| enterStateCommon | function | Common enter state callback |
|
|
1826
|
+
| enterState | function | Enter state callback |
|
|
1827
|
+
| transition | function \| object \| array | Transition animation (forward only) |
|
|
1828
|
+
| steadyStateCommon | function | Common steady state |
|
|
1829
|
+
| steadyState | function | Steady state callback |
|
|
1830
|
+
| leaveStateCommon | function | Common leave state |
|
|
1831
|
+
| leaveState | function | Leave state callback |
|
|
1832
|
+
| form | string \| string[] | Equation form(s) |
|
|
1833
|
+
| fromForm | string \| string[] | Previous form before transition |
|
|
1834
|
+
| text | OBJ_FormattedText | Text content |
|
|
1835
|
+
| scenarioCommon | string \| string[] | Common scenario |
|
|
1836
|
+
| scenario | string \| string[] | Scenario |
|
|
1837
|
+
| animate | `'move'` \| `'dissolve'` \| `'moveFrom'` \| `'pulse'` \| `'dissolveInThenMove'` | Form animation type |
|
|
1838
|
+
| clear | boolean | Don't inherit common properties |
|
|
1839
|
+
| modifiers | OBJ_TextModifiersDefinition | Text modifiers |
|
|
1840
|
+
| modifiersCommon | OBJ_TextModifiersDefinition | Common text modifiers |
|
|
1841
|
+
| time | string \| number | Recorder: absolute transition time |
|
|
1842
|
+
| delta | number | Recorder: time delta from last slide |
|
|
1843
|
+
|
|
1844
|
+
### Slide Lifecycle
|
|
1845
|
+
|
|
1846
|
+
`enterState` → `transition(done)` → `steadyState`. Each slide should fully define its state.
|
|
1847
|
+
|
|
1848
|
+
The `transition` callback receives `(done, index, from)`. The `done` callback **must** be called to progress to steady state.
|
|
1849
|
+
|
|
1850
|
+
### SlideNavigator Methods
|
|
1851
|
+
|
|
1852
|
+
```js
|
|
1853
|
+
const nav = new Fig.SlideNavigator({ collection: figure.elements, slides });
|
|
1854
|
+
// or
|
|
1855
|
+
const nav = figure.addSlideNavigator();
|
|
1856
|
+
nav.loadSlides(slides);
|
|
1857
|
+
|
|
1858
|
+
nav.goToSlide(0);
|
|
1859
|
+
nav.nextSlide();
|
|
1860
|
+
nav.prevSlide();
|
|
1861
|
+
nav.currentSlideIndex; // Current index
|
|
1862
|
+
```
|
|
1863
|
+
|
|
1864
|
+
### Verbose Syntax
|
|
1865
|
+
```js
|
|
1866
|
+
const slides = [
|
|
1867
|
+
{
|
|
1868
|
+
show: [eqn, description],
|
|
1869
|
+
steadyState: () => { eqn.showForm('0'); },
|
|
1870
|
+
},
|
|
1871
|
+
{
|
|
1872
|
+
show: [eqn, description],
|
|
1873
|
+
enterState: () => { eqn.showForm('0'); },
|
|
1874
|
+
transition: (done) => {
|
|
1875
|
+
eqn.animations.new()
|
|
1876
|
+
.goToForm({ target: '1', animate: 'move' })
|
|
1877
|
+
.whenFinished(done)
|
|
1878
|
+
.start();
|
|
1879
|
+
},
|
|
1880
|
+
steadyState: () => { eqn.showForm('1'); },
|
|
1881
|
+
},
|
|
1882
|
+
];
|
|
1883
|
+
```
|
|
1884
|
+
|
|
1885
|
+
### Succinct Equation Syntax
|
|
1886
|
+
```js
|
|
1887
|
+
const nav = new Fig.SlideNavigator({
|
|
1888
|
+
collection: figure.elements, equation: eqn, text: description,
|
|
1889
|
+
slides: [
|
|
1890
|
+
{ form: '0', text: 'Start here' },
|
|
1891
|
+
{ text: 'Next step' },
|
|
1892
|
+
{ form: '1' },
|
|
1893
|
+
],
|
|
1894
|
+
});
|
|
1895
|
+
```
|
|
1896
|
+
|
|
1897
|
+
### Shortcut Animation Syntax (OBJ_AnimationDefinition)
|
|
1898
|
+
|
|
1899
|
+
```js
|
|
1900
|
+
nav.loadSlides([
|
|
1901
|
+
{
|
|
1902
|
+
showCommon: 'sq1',
|
|
1903
|
+
enterStateCommon: () => { sq1.setPosition([-0.5, 0.5]); },
|
|
1904
|
+
},
|
|
1905
|
+
{ transition: { in: 'sq2' } }, // dissolve in
|
|
1906
|
+
{ transition: { position: 'sq2', target: [0.3, 0.5], duration: 1 } }, // move
|
|
1907
|
+
{
|
|
1908
|
+
transition: [ // sequence
|
|
1909
|
+
{ position: 'sq1', target: [-0.3, 0.5], duration: 1 },
|
|
1910
|
+
{ rotation: 'sq1', target: Math.PI / 4, duration: 1 },
|
|
1911
|
+
],
|
|
1912
|
+
},
|
|
1913
|
+
{
|
|
1914
|
+
transition: [ // parallel (nested)
|
|
1915
|
+
[
|
|
1916
|
+
{ rotation: 'sq1', target: 0, duration: 1 },
|
|
1917
|
+
{ rotation: 'sq2', target: 0, duration: 1 },
|
|
1918
|
+
],
|
|
1919
|
+
{ out: ['sq1', 'sq2'] }, // dissolve out
|
|
1920
|
+
],
|
|
1921
|
+
},
|
|
1922
|
+
]);
|
|
1923
|
+
```
|
|
1924
|
+
|
|
1925
|
+
Shortcut animation keys: `in`, `out`, `position`, `rotation`, `scale`, `scenario`, `scenarios`, `dim`, `undim`, `pulse`, `trigger`, `delay`, `goToForm`.
|
|
1926
|
+
|
|
1927
|
+
---
|
|
1928
|
+
|
|
1929
|
+
## 11. FigureElement Methods
|
|
1930
|
+
|
|
1931
|
+
### Transform Methods
|
|
1932
|
+
```js
|
|
1933
|
+
element.setPosition([x, y]) // or setPosition(x, y)
|
|
1934
|
+
element.getPosition() // returns Point
|
|
1935
|
+
element.getPosition('figure') // in figure space
|
|
1936
|
+
element.setRotation(angle)
|
|
1937
|
+
element.getRotation() // returns number
|
|
1938
|
+
element.setScale(x, y) // or setScale(uniformScale)
|
|
1939
|
+
element.getScale() // returns Point
|
|
1940
|
+
element.setTransform(transform)
|
|
1941
|
+
element.getTransform() // returns Transform
|
|
1942
|
+
```
|
|
1943
|
+
|
|
1944
|
+
### Visibility Methods
|
|
1945
|
+
```js
|
|
1946
|
+
element.show()
|
|
1947
|
+
element.hide()
|
|
1948
|
+
element.toggleShow()
|
|
1949
|
+
element.showAll() // Recursive
|
|
1950
|
+
element.hideAll() // Recursive
|
|
1951
|
+
// Collections:
|
|
1952
|
+
collection.show(elementPath) // Show specific children
|
|
1953
|
+
collection.hide(elementPath)
|
|
1954
|
+
collection.showOnly(elementPath) // Hide all, show specified
|
|
1955
|
+
```
|
|
1956
|
+
|
|
1957
|
+
### Color Methods
|
|
1958
|
+
```js
|
|
1959
|
+
element.setColor([r, g, b, a])
|
|
1960
|
+
element.setOpacity(0.5) // 0-1
|
|
1961
|
+
element.dim() // Set dimColor
|
|
1962
|
+
element.undim() // Set defaultColor
|
|
1963
|
+
element.setDimColor([r, g, b, a])
|
|
1964
|
+
// Collections:
|
|
1965
|
+
collection.dim(elementPath) // Dim specific children
|
|
1966
|
+
collection.undim(elementPath)
|
|
1967
|
+
collection.highlight(elementPath) // Undim specified, dim rest
|
|
1968
|
+
```
|
|
1969
|
+
|
|
1970
|
+
### Scenario Methods
|
|
1971
|
+
```js
|
|
1972
|
+
element.setScenario('name')
|
|
1973
|
+
element.setScenario({ position: [0, 0], rotation: 0, color: [1, 0, 0, 1] })
|
|
1974
|
+
element.saveScenario('name')
|
|
1975
|
+
element.getCurrentScenario()
|
|
1976
|
+
// Collections:
|
|
1977
|
+
collection.setScenarios('name') // All children
|
|
1978
|
+
collection.saveScenarios('name', ['position', 'rotation'])
|
|
1979
|
+
collection.getAllElementsWithScenario('name')
|
|
1980
|
+
```
|
|
1981
|
+
|
|
1982
|
+
### Touch/Move Methods
|
|
1983
|
+
```js
|
|
1984
|
+
element.setTouchable() // or setTouchable(false)
|
|
1985
|
+
element.setMovable()
|
|
1986
|
+
element.setMove({ type: 'rotation', bounds: ... })
|
|
1987
|
+
element.isMoving()
|
|
1988
|
+
element.startMovingFreely()
|
|
1989
|
+
element.stopMovingFreely()
|
|
1990
|
+
element.click() // Programmatic click
|
|
1991
|
+
```
|
|
1992
|
+
|
|
1993
|
+
### Animation Methods
|
|
1994
|
+
```js
|
|
1995
|
+
element.pulse({ scale: 1.5, duration: 1 })
|
|
1996
|
+
element.animations.new()...start()
|
|
1997
|
+
element.isAnimating()
|
|
1998
|
+
element.stopAnimating() // or 'freeze'|'cancel'|'complete'
|
|
1999
|
+
element.stopAnimating('complete', 'animName') // Stop specific animation
|
|
2000
|
+
element.getRemainingAnimationTime()
|
|
2001
|
+
element.getRemainingAnimationTime('animName')
|
|
2002
|
+
```
|
|
2003
|
+
|
|
2004
|
+
Stop options: `'freeze'` (stop at current state), `'cancel'` (cancel), `'complete'` (jump to end), `'animateToComplete'` (animate to end), `'dissolveToComplete'` (dissolve to end).
|
|
2005
|
+
|
|
2006
|
+
### Text Methods
|
|
2007
|
+
```js
|
|
2008
|
+
textElement.setText('new text')
|
|
2009
|
+
textElement.setText({ text: 'new', font: { size: 0.3 }, xAlign: 'center' })
|
|
2010
|
+
```
|
|
2011
|
+
|
|
2012
|
+
### Collection Element Access
|
|
2013
|
+
```js
|
|
2014
|
+
collection.getElement('child') // By name
|
|
2015
|
+
collection.getElement('a.b.c') // Dot-path access
|
|
2016
|
+
collection._childName // Direct property access
|
|
2017
|
+
collection.getChildren() // All direct children
|
|
2018
|
+
collection.getAllElements() // All recursive
|
|
2019
|
+
collection.getAllPrimitives() // All recursive primitives
|
|
2020
|
+
collection.add('name', element) // Add child
|
|
2021
|
+
collection.remove('name') // Remove child
|
|
2022
|
+
collection.toFront('name') // Change draw order
|
|
2023
|
+
collection.toBack('name')
|
|
2024
|
+
```
|
|
2025
|
+
|
|
2026
|
+
### Boundary Methods
|
|
2027
|
+
```js
|
|
2028
|
+
element.getBoundingRect('figure') // In figure space
|
|
2029
|
+
element.getRelativeBoundingRect()
|
|
2030
|
+
element.getCenterFigurePosition()
|
|
2031
|
+
element.getBorder('figure', 'touchBorder')
|
|
2032
|
+
```
|
|
2033
|
+
|
|
2034
|
+
### Coordinate Space Transform
|
|
2035
|
+
```js
|
|
2036
|
+
element.transformPoint([0, 0], 'local', 'figure')
|
|
2037
|
+
element.pointFromSpaceToSpace(point, 'draw', 'figure')
|
|
2038
|
+
// Spaces: 'draw', 'local', 'figure', 'gl', 'pixel'
|
|
2039
|
+
element.spaceTransformMatrix('local', 'figure')
|
|
2040
|
+
element.pixelToPlane(pixel, 'figure', Plane.xy())
|
|
2041
|
+
element.glToPlane(glPoint, 'figure')
|
|
2042
|
+
```
|
|
2043
|
+
|
|
2044
|
+
### Batch Transform/Color Methods (Collections)
|
|
2045
|
+
```js
|
|
2046
|
+
collection.getElementTransforms()
|
|
2047
|
+
collection.setElementTransforms(transformsObj)
|
|
2048
|
+
collection.getElementColors()
|
|
2049
|
+
collection.setElementColors(colorsObj)
|
|
2050
|
+
collection.animateToTransforms(transformsObj, duration)
|
|
2051
|
+
collection.animateToColors(colorsObj, duration)
|
|
2052
|
+
```
|
|
2053
|
+
|
|
2054
|
+
---
|
|
2055
|
+
|
|
2056
|
+
## 12. Geometry Utilities
|
|
2057
|
+
|
|
2058
|
+
### Point Class
|
|
2059
|
+
```js
|
|
2060
|
+
const p = new Fig.Point(1, 2); // or new Fig.Point(1, 2, 3) for 3D
|
|
2061
|
+
p.x; p.y; p.z;
|
|
2062
|
+
p.add(other) // Returns new Point
|
|
2063
|
+
p.sub(other)
|
|
2064
|
+
p.scale(scalar)
|
|
2065
|
+
p.length() // Distance from origin
|
|
2066
|
+
p.distance(otherPoint)
|
|
2067
|
+
p.normalize() // Unit vector
|
|
2068
|
+
p.rotate(angle, center?)
|
|
2069
|
+
p.round(precision)
|
|
2070
|
+
p.isEqualTo(other, precision?)
|
|
2071
|
+
p.dotProduct(other)
|
|
2072
|
+
p.crossProduct(other)
|
|
2073
|
+
p.toPolar() // { mag, angle }
|
|
2074
|
+
p.transformBy(matrix)
|
|
2075
|
+
```
|
|
2076
|
+
|
|
2077
|
+
### Transform Class
|
|
2078
|
+
```js
|
|
2079
|
+
const t = new Fig.Transform()
|
|
2080
|
+
.translate(x, y)
|
|
2081
|
+
.rotate(angle)
|
|
2082
|
+
.scale(sx, sy);
|
|
2083
|
+
|
|
2084
|
+
t.t() // Get translation as Point
|
|
2085
|
+
t.r() // Get rotation angle
|
|
2086
|
+
t.s() // Get scale as Point
|
|
2087
|
+
t.matrix() // Get 4x4 matrix
|
|
2088
|
+
t.updateTranslation(point)
|
|
2089
|
+
t.updateRotation(angle)
|
|
2090
|
+
t.updateScale(scale)
|
|
2091
|
+
t.isEqualTo(other, precision?)
|
|
2092
|
+
t._dup() // Duplicate
|
|
2093
|
+
```
|
|
2094
|
+
|
|
2095
|
+
### Line Class
|
|
2096
|
+
```js
|
|
2097
|
+
const l = new Fig.Line([0, 0], [1, 1]); // Finite segment
|
|
2098
|
+
const l2 = new Fig.Line([0, 0], [1, 1], 0); // Infinite line
|
|
2099
|
+
l.length()
|
|
2100
|
+
l.angle()
|
|
2101
|
+
l.midPoint()
|
|
2102
|
+
l.pointAtPercent(0.5)
|
|
2103
|
+
l.hasPointOn(point)
|
|
2104
|
+
l.distanceToPoint(point)
|
|
2105
|
+
l.intersectsWith(otherLine) // { intersect, collinear, onLines }
|
|
2106
|
+
l.isParallelTo(otherLine)
|
|
2107
|
+
l.offset('positive', distance)
|
|
2108
|
+
l.reverse()
|
|
2109
|
+
```
|
|
2110
|
+
|
|
2111
|
+
### Plane Class
|
|
2112
|
+
```js
|
|
2113
|
+
const pl = new Fig.Plane([0, 0, 0], [0, 0, 1]); // point + normal
|
|
2114
|
+
Plane.xy(); Plane.xz(); Plane.yz();
|
|
2115
|
+
pl.hasPointOn(point)
|
|
2116
|
+
pl.distanceToPoint(point)
|
|
2117
|
+
pl.pointProjection(point)
|
|
2118
|
+
pl.intersectsWith(otherPlane) // Returns Line or null
|
|
2119
|
+
pl.lineIntersect(line) // Returns Point or null
|
|
2120
|
+
```
|
|
2121
|
+
|
|
2122
|
+
### Rect Class
|
|
2123
|
+
```js
|
|
2124
|
+
const r = new Fig.Rect(left, bottom, width, height);
|
|
2125
|
+
r.left; r.bottom; r.right; r.top; r.width; r.height;
|
|
2126
|
+
r.center()
|
|
2127
|
+
r.isPointInside(point)
|
|
2128
|
+
```
|
|
2129
|
+
|
|
2130
|
+
### Utility Functions
|
|
2131
|
+
```js
|
|
2132
|
+
Fig.range(start, stop, step) // [start, start+step, ..., stop]
|
|
2133
|
+
Fig.round(value, precision) // Round to N decimal places
|
|
2134
|
+
Fig.rand(min, max) // Random number
|
|
2135
|
+
Fig.randInt(min, max) // Random integer
|
|
2136
|
+
Fig.polarToRect(magnitude, angle) // Returns Point
|
|
2137
|
+
Fig.rectToPolar(x, y) // Returns { mag, angle }
|
|
2138
|
+
Fig.deg(radians) // Radians to degrees
|
|
2139
|
+
Fig.normAngle(angle) // Normalize to 0-2π
|
|
2140
|
+
Fig.clipAngle(angle, range) // Clip to range ('0to360', '-180to180')
|
|
2141
|
+
Fig.minAngleDiff(a1, a2) // Minimum absolute angle difference
|
|
2142
|
+
Fig.threePointAngle(p2, p1, p3) // Angle at p1
|
|
2143
|
+
|
|
2144
|
+
// 3D geometry functions
|
|
2145
|
+
Fig.surfaceGrid({ x, y, z }) // Generate surface point grid
|
|
2146
|
+
// x: [min, max, step], y: [min, max, step], z: (x, y) => number
|
|
2147
|
+
|
|
2148
|
+
// Conversion
|
|
2149
|
+
Fig.toNumbers(points) // Point[] → flat number[]
|
|
2150
|
+
Fig.toPoints(numbers) // flat number[] → Point[]
|
|
2151
|
+
Fig.numbersToPoints(numbers, dim?)
|
|
2152
|
+
Fig.pointsToNumbers(points, dim?)
|
|
2153
|
+
|
|
2154
|
+
// 3D shape vertex generators (return [points, normals])
|
|
2155
|
+
Fig.cube({ side })
|
|
2156
|
+
Fig.sphere({ radius, sides })
|
|
2157
|
+
Fig.cylinder({ radius, length, sides })
|
|
2158
|
+
Fig.cone({ radius, length, sides })
|
|
2159
|
+
Fig.revolve({ profile, sides })
|
|
2160
|
+
Fig.polygon({ sides, radius, center, close, direction })
|
|
2161
|
+
```
|
|
2162
|
+
|
|
2163
|
+
---
|
|
2164
|
+
|
|
2165
|
+
## 13. OBJ_Scene
|
|
2166
|
+
|
|
2167
|
+
### OBJ_Scene
|
|
2168
|
+
|
|
2169
|
+
| Property | Type | Default | Description |
|
|
2170
|
+
|---|---|---|---|
|
|
2171
|
+
| style | `'orthographic'` \| `'perspective'` | | Projection style (set for 3D) |
|
|
2172
|
+
| left | number | `-1` | 2D: left boundary |
|
|
2173
|
+
| right | number | `1` | 2D: right boundary |
|
|
2174
|
+
| bottom | number | `-1` | 2D: bottom boundary |
|
|
2175
|
+
| top | number | `1` | 2D: top boundary |
|
|
2176
|
+
| near | number | `0.1` | Near clip plane (3D) |
|
|
2177
|
+
| far | number | `100` | Far clip plane (3D) |
|
|
2178
|
+
| aspectRatio | number | | Aspect ratio override |
|
|
2179
|
+
| fieldOfView | number | | Perspective field of view (radians) |
|
|
2180
|
+
| light | OBJ_Light | | Lighting configuration |
|
|
2181
|
+
| camera | OBJ_Camera | | Camera configuration |
|
|
2182
|
+
| zoom | number | | Zoom level |
|
|
2183
|
+
| pan | TypeParsablePoint | | Pan offset |
|
|
2184
|
+
|
|
2185
|
+
### OBJ_Camera
|
|
2186
|
+
|
|
2187
|
+
| Property | Type | Default | Description |
|
|
2188
|
+
|---|---|---|---|
|
|
2189
|
+
| position | TypeParsablePoint | `[0, 0, 2]` | Camera position |
|
|
2190
|
+
| lookAt | TypeParsablePoint | `[0, 0, 0]` | Look-at target |
|
|
2191
|
+
| up | TypeParsablePoint | `[0, 1, 0]` | Up vector |
|
|
2192
|
+
|
|
2193
|
+
### OBJ_Light
|
|
2194
|
+
|
|
2195
|
+
| Property | Type | Default | Description |
|
|
2196
|
+
|---|---|---|---|
|
|
2197
|
+
| directional | TypeParsablePoint | `[0.7, 0.5, 1]` | Directional light vector |
|
|
2198
|
+
| ambient | number | `0.4` | Ambient light level (0-1) |
|
|
2199
|
+
| point | TypeParsablePoint | | Point light position |
|
|
2200
|
+
|
|
2201
|
+
### 2D Scene
|
|
2202
|
+
```js
|
|
2203
|
+
// Simple: scene as [x, y, width, height]
|
|
2204
|
+
new Fig.Figure({ scene: [-2, -2, 4, 4] });
|
|
2205
|
+
```
|
|
2206
|
+
|
|
2207
|
+
### 3D Scene
|
|
2208
|
+
```js
|
|
2209
|
+
new Fig.Figure({
|
|
2210
|
+
scene: {
|
|
2211
|
+
style: 'orthographic', // or 'perspective'
|
|
2212
|
+
camera: { position: [2, 1, 2], lookAt: [0, 0, 0], up: [0, 1, 0] },
|
|
2213
|
+
light: { directional: [0.7, 0.5, 1], ambient: 0.4 },
|
|
2214
|
+
near: 0.1,
|
|
2215
|
+
far: 10,
|
|
2216
|
+
},
|
|
2217
|
+
});
|
|
2218
|
+
```
|
|
2219
|
+
|
|
2220
|
+
### Scene Methods
|
|
2221
|
+
```js
|
|
2222
|
+
figure.scene.setCamera({ position: [1, 1, 2] });
|
|
2223
|
+
figure.scene.setLight({ directional: [0.7, 0.5, 1] });
|
|
2224
|
+
figure.scene.setProjection({ style: 'orthographic' });
|
|
2225
|
+
figure.scene.setPanZoom(pan, zoom);
|
|
2226
|
+
figure.scene.figureToGL(point);
|
|
2227
|
+
figure.scene.glToFigure(point);
|
|
2228
|
+
```
|
|
2229
|
+
|
|
2230
|
+
---
|
|
2231
|
+
|
|
2232
|
+
## 14. Recorder
|
|
2233
|
+
|
|
2234
|
+
FigureOne supports recording and playback of figure interactions.
|
|
2235
|
+
|
|
2236
|
+
```js
|
|
2237
|
+
const recorder = figure.recorder;
|
|
2238
|
+
|
|
2239
|
+
// Record
|
|
2240
|
+
recorder.start();
|
|
2241
|
+
// ... user interactions ...
|
|
2242
|
+
recorder.stop();
|
|
2243
|
+
recorder.save('recording.json');
|
|
2244
|
+
|
|
2245
|
+
// Playback
|
|
2246
|
+
recorder.load('recording.json');
|
|
2247
|
+
recorder.play();
|
|
2248
|
+
recorder.pause();
|
|
2249
|
+
recorder.seek(timeInSeconds);
|
|
2250
|
+
```
|
|
2251
|
+
|
|
2252
|
+
The recorder captures all element state changes (transforms, colors, visibility) and user interactions. Playback recreates the exact sequence. SlideNavigator slides can include `time` and `delta` properties for automatic recorder timing.
|
|
2253
|
+
|
|
2254
|
+
---
|
|
2255
|
+
|
|
2256
|
+
## 15. Common Patterns and Tips
|
|
2257
|
+
|
|
2258
|
+
### Element Naming and Access
|
|
2259
|
+
```js
|
|
2260
|
+
// Named elements are accessible as underscore-prefixed properties
|
|
2261
|
+
figure.add({ make: 'polygon', name: 'myShape', sides: 6 });
|
|
2262
|
+
figure.elements._myShape;
|
|
2263
|
+
|
|
2264
|
+
// Or via getElement with dot-path
|
|
2265
|
+
figure.getElement('myShape');
|
|
2266
|
+
|
|
2267
|
+
// Nested collections
|
|
2268
|
+
figure.add({
|
|
2269
|
+
make: 'collection',
|
|
2270
|
+
name: 'group',
|
|
2271
|
+
elements: [
|
|
2272
|
+
{ make: 'polygon', name: 'a', sides: 4 },
|
|
2273
|
+
{ make: 'polygon', name: 'b', sides: 6 },
|
|
2274
|
+
],
|
|
2275
|
+
});
|
|
2276
|
+
figure.getElement('group.a');
|
|
2277
|
+
figure.elements._group._a;
|
|
2278
|
+
```
|
|
2279
|
+
|
|
2280
|
+
### mods Property
|
|
2281
|
+
All elements support a `mods` property for setting any FigureElement property after construction:
|
|
2282
|
+
|
|
2283
|
+
```js
|
|
2284
|
+
figure.add({
|
|
2285
|
+
make: 'polygon', sides: 6, radius: 0.3,
|
|
2286
|
+
mods: {
|
|
2287
|
+
isTouchable: true,
|
|
2288
|
+
touchBorder: 0.1,
|
|
2289
|
+
dimColor: [0.7, 0.7, 0.7, 1],
|
|
2290
|
+
scenarios: {
|
|
2291
|
+
default: { position: [0, 0] },
|
|
2292
|
+
moved: { position: [0.5, 0.5] },
|
|
2293
|
+
},
|
|
2294
|
+
},
|
|
2295
|
+
});
|
|
2296
|
+
```
|
|
2297
|
+
|
|
2298
|
+
### Equation Element Naming Conventions
|
|
2299
|
+
- `'elementName'` — text element displaying `elementName`
|
|
2300
|
+
- `'_ text'` — text element displaying ` text` (underscore prefix stripped)
|
|
2301
|
+
- `'a_1'`, `'a_2'` — copies of `a` (number suffix is index)
|
|
2302
|
+
- `{ symbol: 'type' }` — symbol element
|
|
2303
|
+
- Undeclared strings in forms are auto-created as text elements
|
|
2304
|
+
|
|
2305
|
+
### Inline Symbol Shortcuts
|
|
2306
|
+
Symbols can be created inline in forms without pre-declaring in elements:
|
|
2307
|
+
```js
|
|
2308
|
+
// One-use inline symbol
|
|
2309
|
+
{ frac: ['a', 'vinculum', 'b'] } // Auto-creates vinculum symbol
|
|
2310
|
+
|
|
2311
|
+
// Named inline with customization
|
|
2312
|
+
{ frac: ['a', { vinculum: { lineWidth: 0.004 } }, 'b'] }
|
|
2313
|
+
|
|
2314
|
+
// Multiple uses need unique names (suffix with _name)
|
|
2315
|
+
{ frac: ['a', 'v1_vinculum', { frac: ['c', 'v2_vinculum', 'd'] }] }
|
|
2316
|
+
```
|
|
2317
|
+
|
|
2318
|
+
### Coordinate Spaces
|
|
2319
|
+
- `'draw'` — Drawing canvas coordinates (element's own draw space)
|
|
2320
|
+
- `'local'` — Element's local space (after element's transform)
|
|
2321
|
+
- `'figure'` — Figure root coordinates (what you see on screen)
|
|
2322
|
+
- `'gl'` — WebGL clip coordinates (-1 to 1)
|
|
2323
|
+
- `'pixel'` — Screen pixel coordinates
|
|
2324
|
+
|
|
2325
|
+
### TypeParsableBounds
|
|
2326
|
+
Movement bounds can be defined as:
|
|
2327
|
+
```js
|
|
2328
|
+
// Rectangle bounds
|
|
2329
|
+
{ left: -1, bottom: -1, right: 1, top: 1 }
|
|
2330
|
+
|
|
2331
|
+
// Or as a Rect
|
|
2332
|
+
new Fig.Rect(-1, -1, 2, 2)
|
|
2333
|
+
|
|
2334
|
+
// Rotation bounds
|
|
2335
|
+
{ min: 0, max: Math.PI }
|
|
2336
|
+
```
|
|
2337
|
+
|
|
2338
|
+
### FigureElement Notifications
|
|
2339
|
+
Common notification events:
|
|
2340
|
+
- `'setTransform'` — element transform changed
|
|
2341
|
+
- `'onClick'` — element clicked/touched
|
|
2342
|
+
- `'animationsFinished'` — all animations completed
|
|
2343
|
+
- `'setFigure'` — element added to figure
|
|
2344
|
+
- `'beforeDraw'` — before element is drawn
|
|
2345
|
+
- `'afterDraw'` — after element is drawn
|
|
2346
|
+
- `'setColor'` — color changed
|
|
2347
|
+
|
|
2348
|
+
```js
|
|
2349
|
+
element.notifications.add('setTransform', (transform) => {
|
|
2350
|
+
console.log('New position:', transform.t());
|
|
2351
|
+
});
|
|
2352
|
+
element.notifications.remove('setTransform');
|
|
2353
|
+
```
|
|
2354
|
+
|
|
2355
|
+
### Animation Progression Functions
|
|
2356
|
+
Built-in progression functions:
|
|
2357
|
+
- `'linear'` — constant speed
|
|
2358
|
+
- `'easeinout'` — slow start and end (default for most steps)
|
|
2359
|
+
- `'easein'` — slow start
|
|
2360
|
+
- `'easeout'` — slow end
|
|
2361
|
+
- Custom: `(percent) => mappedPercent` (0-1 input, 0-1 output)
|
|
2362
|
+
|
|
2363
|
+
---
|
|
2364
|
+
|
|
2365
|
+
## 16. Complete Examples
|
|
2366
|
+
|
|
2367
|
+
### Interactive Geometry Figure
|
|
2368
|
+
|
|
2369
|
+
```js
|
|
2370
|
+
const figure = new Fig.Figure({ scene: [-2, -1.5, 4, 3] });
|
|
2371
|
+
|
|
2372
|
+
// Triangle with labeled sides and angles
|
|
2373
|
+
const tri = figure.add({
|
|
2374
|
+
make: 'collections.polyline',
|
|
2375
|
+
points: [[-1, -0.5], [1, -0.5], [0, 0.8]],
|
|
2376
|
+
close: true, width: 0.02,
|
|
2377
|
+
color: [0, 0.5, 1, 1],
|
|
2378
|
+
side: {
|
|
2379
|
+
label: { text: null, precision: 1 },
|
|
2380
|
+
offset: 0.15,
|
|
2381
|
+
},
|
|
2382
|
+
angle: {
|
|
2383
|
+
curve: { radius: 0.25, width: 0.01 },
|
|
2384
|
+
label: { text: null, precision: 0 },
|
|
2385
|
+
},
|
|
2386
|
+
pad: {
|
|
2387
|
+
color: [0, 0.5, 1, 0.3],
|
|
2388
|
+
radius: 0.15,
|
|
2389
|
+
isMovable: true,
|
|
2390
|
+
boundary: [-1.8, -1.3, 3.6, 2.6],
|
|
2391
|
+
},
|
|
2392
|
+
});
|
|
2393
|
+
```
|
|
2394
|
+
|
|
2395
|
+
### Equation with Animated Form Transitions
|
|
2396
|
+
|
|
2397
|
+
```js
|
|
2398
|
+
const eqn = figure.add({
|
|
2399
|
+
make: 'equation',
|
|
2400
|
+
elements: {
|
|
2401
|
+
v: { symbol: 'vinculum' },
|
|
2402
|
+
lb: { symbol: 'bracket', side: 'left' },
|
|
2403
|
+
rb: { symbol: 'bracket', side: 'right' },
|
|
2404
|
+
r: { symbol: 'radical' },
|
|
2405
|
+
equals: ' = ',
|
|
2406
|
+
plus: ' + ',
|
|
2407
|
+
minus: ' \u2212 ',
|
|
2408
|
+
_4: '4',
|
|
2409
|
+
},
|
|
2410
|
+
phrases: {
|
|
2411
|
+
bPlusMinus: ['b', 'plus', { root: ['r', [{ sup: ['b_1', '2_1'] }, 'minus', '_4', 'a', 'c']] }],
|
|
2412
|
+
},
|
|
2413
|
+
formDefaults: { alignment: { fixTo: 'equals' } },
|
|
2414
|
+
forms: {
|
|
2415
|
+
quadratic: ['a', { sup: ['x_1', '2'] }, 'plus', 'b_2', 'x_2', 'plus', 'c_1', 'equals', '0'],
|
|
2416
|
+
solution: ['x', 'equals', { frac: [['minus', 'b', 'plus', { root: ['r', [{ sup: ['b_1', '2_1'] }, 'minus', '_4', 'a', 'c']] }], 'v', ['2', 'a_1']] }],
|
|
2417
|
+
},
|
|
2418
|
+
formSeries: { default: ['quadratic', 'solution'] },
|
|
2419
|
+
});
|
|
2420
|
+
|
|
2421
|
+
// Animate between forms
|
|
2422
|
+
eqn.showForm('quadratic');
|
|
2423
|
+
eqn.animations.new()
|
|
2424
|
+
.delay(2)
|
|
2425
|
+
.goToForm({ target: 'solution', animate: 'move', duration: 2 })
|
|
2426
|
+
.start();
|
|
2427
|
+
```
|
|
2428
|
+
|
|
2429
|
+
### SlideNavigator with Equations and Text
|
|
2430
|
+
|
|
2431
|
+
```js
|
|
2432
|
+
const figure = new Fig.Figure();
|
|
2433
|
+
|
|
2434
|
+
const description = figure.add({
|
|
2435
|
+
make: 'ftext',
|
|
2436
|
+
font: { size: 0.08, family: 'Arial' },
|
|
2437
|
+
xAlign: 'center',
|
|
2438
|
+
position: [0, -0.6],
|
|
2439
|
+
});
|
|
2440
|
+
|
|
2441
|
+
const eqn = figure.add({
|
|
2442
|
+
make: 'equation',
|
|
2443
|
+
elements: { v: { symbol: 'vinculum' }, equals: ' = ' },
|
|
2444
|
+
forms: {
|
|
2445
|
+
0: ['a', 'equals', { frac: ['b', 'v', 'c'] }],
|
|
2446
|
+
1: ['a', 'equals', { frac: [['b', '_ + ', 'd'], 'v', 'c'] }],
|
|
2447
|
+
2: ['a', 'equals', { frac: [['b', '_ + ', 'd'], 'v', ['c', '_ + ', 'e']] }],
|
|
2448
|
+
},
|
|
2449
|
+
formSeries: { default: ['0', '1', '2'] },
|
|
2450
|
+
});
|
|
2451
|
+
|
|
2452
|
+
const nav = figure.addSlideNavigator({
|
|
2453
|
+
equation: eqn,
|
|
2454
|
+
text: description,
|
|
2455
|
+
slides: [
|
|
2456
|
+
{ form: '0', text: 'Start with a simple fraction' },
|
|
2457
|
+
{ form: '1', text: 'Add |d| to the numerator', modifiers: { d: { font: { color: [1, 0, 0, 1] } } } },
|
|
2458
|
+
{ form: '2', text: 'Add |e| to the denominator', modifiers: { e: { font: { color: [0, 0, 1, 1] } } } },
|
|
2459
|
+
],
|
|
2460
|
+
});
|
|
2461
|
+
nav.goToSlide(0);
|
|
2462
|
+
```
|
|
2463
|
+
|
|
2464
|
+
### 3D Scene with Multiple Shapes
|
|
2465
|
+
|
|
2466
|
+
```js
|
|
2467
|
+
const figure = new Fig.Figure({
|
|
2468
|
+
scene: {
|
|
2469
|
+
style: 'orthographic',
|
|
2470
|
+
camera: { position: [2, 1, 2], lookAt: [0, 0, 0] },
|
|
2471
|
+
light: { directional: [0.7, 0.5, 1], ambient: 0.4 },
|
|
2472
|
+
},
|
|
2473
|
+
});
|
|
2474
|
+
|
|
2475
|
+
figure.add([
|
|
2476
|
+
{ make: 'cube', side: 0.3, position: [-0.5, 0, 0], color: [1, 0, 0, 1] },
|
|
2477
|
+
{ make: 'sphere', radius: 0.2, sides: 20, normals: 'curve', position: [0, 0, 0], color: [0, 0.7, 0, 1] },
|
|
2478
|
+
{ make: 'cylinder', radius: 0.15, length: 0.4, sides: 20, normals: 'curve', position: [0.5, 0, 0], color: [0, 0.3, 1, 1] },
|
|
2479
|
+
{ make: 'collections.axis3', length: 0.8, width: 0.01 },
|
|
2480
|
+
{ make: 'cameraControl' },
|
|
2481
|
+
]);
|
|
2482
|
+
```
|
|
2483
|
+
|
|
2484
|
+
### Plot with Zoom and Pan
|
|
2485
|
+
|
|
2486
|
+
```js
|
|
2487
|
+
const x = Fig.range(0, 4 * Math.PI, 0.05);
|
|
2488
|
+
const y = x.map(v => Math.sin(v));
|
|
2489
|
+
|
|
2490
|
+
figure.add({
|
|
2491
|
+
make: 'collections.plot',
|
|
2492
|
+
width: 1.6, height: 1, position: [-0.8, -0.5],
|
|
2493
|
+
x: { start: 0, stop: 4 * Math.PI, title: 'x', step: Math.PI, labels: { format: v => `${(v / Math.PI).toFixed(0)}π` } },
|
|
2494
|
+
y: { start: -1.2, stop: 1.2, title: 'sin(x)', step: 0.5 },
|
|
2495
|
+
trace: { points: x.map((v, i) => [v, y[i]]), color: [1, 0, 0, 1] },
|
|
2496
|
+
zoom: 'xy',
|
|
2497
|
+
pan: 'xy',
|
|
2498
|
+
});
|
|
2499
|
+
```
|