@motionscript/charts 0.1.0-alpha.3 → 0.1.0-alpha.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/LICENSE +201 -201
- package/NOTICE +48 -0
- package/README.md +85 -0
- package/dist/bar-chart/bar-chart.d.ts +28 -13
- package/dist/bar-chart/bar-chart.d.ts.map +1 -1
- package/dist/bar-chart/bar-chart.js +60 -56
- package/dist/bar-chart/bar-chart.js.map +1 -1
- package/dist/bar-chart/category-axis.js.map +1 -1
- package/dist/bar-chart/chart-bars.js.map +1 -1
- package/dist/bar-chart/index.js.map +1 -1
- package/dist/bar-chart/shared.d.ts +3 -3
- package/dist/bar-chart/shared.js +3 -3
- package/dist/bar-chart/shared.js.map +1 -1
- package/dist/browser/chunks/chunk-5ZPBV6BU.js +2 -0
- package/dist/browser/chunks/chunk-5ZPBV6BU.js.map +7 -0
- package/dist/browser/index.js +1 -1
- package/dist/browser/index.js.map +3 -3
- package/dist/browser/kit.js +1 -1
- package/dist/browser/manifest.json +3 -2
- package/dist/engine.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/kit/chart-border.js.map +1 -1
- package/dist/kit/chart-canvas.js.map +1 -1
- package/dist/kit/chart-legend.d.ts +4 -25
- package/dist/kit/chart-legend.d.ts.map +1 -1
- package/dist/kit/chart-legend.js +31 -55
- package/dist/kit/chart-legend.js.map +1 -1
- package/dist/kit/shared.d.ts +29 -6
- package/dist/kit/shared.d.ts.map +1 -1
- package/dist/kit/shared.js +64 -8
- package/dist/kit/shared.js.map +1 -1
- package/dist/kit/vertical-axis.js.map +1 -1
- package/dist/line-chart/chart-line.d.ts +2 -2
- package/dist/line-chart/chart-line.js.map +1 -1
- package/dist/line-chart/chart-region.js.map +1 -1
- package/dist/line-chart/horizontal-axis.js.map +1 -1
- package/dist/line-chart/index.js.map +1 -1
- package/dist/line-chart/line-chart.d.ts +9 -1
- package/dist/line-chart/line-chart.d.ts.map +1 -1
- package/dist/line-chart/line-chart.js +32 -8
- package/dist/line-chart/line-chart.js.map +1 -1
- package/dist/line-chart/shared.d.ts +3 -3
- package/dist/line-chart/shared.d.ts.map +1 -1
- package/dist/line-chart/shared.js +19 -4
- package/dist/line-chart/shared.js.map +1 -1
- package/dist/line-chart/x-scale.d.ts +1 -1
- package/dist/line-chart/x-scale.js +1 -1
- package/dist/line-chart/x-scale.js.map +1 -1
- package/dist/nodes.js.map +1 -1
- package/dist/pie-chart/index.js.map +1 -1
- package/dist/pie-chart/pie-chart.d.ts +2 -2
- package/dist/pie-chart/pie-chart.d.ts.map +1 -1
- package/dist/pie-chart/pie-chart.js +9 -7
- package/dist/pie-chart/pie-chart.js.map +1 -1
- package/dist/pie-chart/pie-legend.js +4 -4
- package/dist/pie-chart/pie-legend.js.map +1 -1
- package/dist/pie-chart/pie-ring.d.ts +13 -4
- package/dist/pie-chart/pie-ring.d.ts.map +1 -1
- package/dist/pie-chart/pie-ring.js +44 -14
- package/dist/pie-chart/pie-ring.js.map +1 -1
- package/dist/pie-chart/shared.d.ts +3 -3
- package/dist/pie-chart/shared.js +3 -3
- package/dist/pie-chart/shared.js.map +1 -1
- package/package.json +6 -5
- package/registry.json +23 -23
- package/src/bar-chart/bar-chart.ts +820 -814
- package/src/bar-chart/category-axis.ts +177 -177
- package/src/bar-chart/chart-bars.ts +310 -310
- package/src/bar-chart/index.ts +31 -31
- package/src/bar-chart/shared.ts +354 -354
- package/src/engine.ts +26 -26
- package/src/index.ts +5 -5
- package/src/kit/chart-border.ts +61 -61
- package/src/kit/chart-canvas.ts +157 -157
- package/src/kit/chart-legend.ts +245 -250
- package/src/kit/shared.ts +733 -675
- package/src/kit/vertical-axis.ts +224 -224
- package/src/line-chart/chart-line.ts +208 -208
- package/src/line-chart/chart-region.ts +135 -135
- package/src/line-chart/horizontal-axis.ts +202 -202
- package/src/line-chart/index.ts +39 -39
- package/src/line-chart/line-chart.ts +961 -929
- package/src/line-chart/shared.ts +473 -459
- package/src/line-chart/x-scale.ts +367 -367
- package/src/nodes.ts +20 -20
- package/src/pie-chart/index.ts +37 -37
- package/src/pie-chart/pie-chart.ts +383 -381
- package/src/pie-chart/pie-legend.ts +159 -159
- package/src/pie-chart/pie-ring.ts +935 -903
- package/src/pie-chart/shared.ts +490 -490
- package/dist/browser/chunks/chunk-RMHQ6GYU.js +0 -2
- package/dist/browser/chunks/chunk-RMHQ6GYU.js.map +0 -7
|
@@ -1,177 +1,177 @@
|
|
|
1
|
-
import {
|
|
2
|
-
command,
|
|
3
|
-
Node2D,
|
|
4
|
-
Rect,
|
|
5
|
-
Text,
|
|
6
|
-
easeOut,
|
|
7
|
-
property,
|
|
8
|
-
insetsOps,
|
|
9
|
-
textOps,
|
|
10
|
-
type CommandArgs,
|
|
11
|
-
type NodeConfig,
|
|
12
|
-
type Node2DProps,
|
|
13
|
-
} from "@motionscript/sdk"
|
|
14
|
-
|
|
15
|
-
import {
|
|
16
|
-
DEFAULT_X_AXIS,
|
|
17
|
-
clampUnit,
|
|
18
|
-
enterBudget,
|
|
19
|
-
type AxisConfig,
|
|
20
|
-
} from "../kit/shared"
|
|
21
|
-
import { at, compose, hold, type Seekable } from "@motionscript/sdk/component"
|
|
22
|
-
|
|
23
|
-
export interface CategoryAxisProps extends Node2DProps {
|
|
24
|
-
/** One caption per category slot, left to right — the chart's rows, in order. */
|
|
25
|
-
categories: string[]
|
|
26
|
-
/** Caption/title text style and gutters — see {@link AxisConfig}. */
|
|
27
|
-
axis: AxisConfig
|
|
28
|
-
/**
|
|
29
|
-
* Caption drawn centred in the gutter beneath the category row. Empty string
|
|
30
|
-
* (the default) hides it.
|
|
31
|
-
*/
|
|
32
|
-
label: string
|
|
33
|
-
/**
|
|
34
|
-
* Per-category opacity multiplier — how the chart's category spotlight reaches
|
|
35
|
-
* the captions, so the name under a dimmed column dims with it. Missing
|
|
36
|
-
* entries read as 1.
|
|
37
|
-
*/
|
|
38
|
-
dims: number[]
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/** How far a caption starts above its slot when it enters, in px. */
|
|
42
|
-
const SLIDE = 24
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* The **categorical** horizontal axis of a {@link BarChart}: a row of
|
|
46
|
-
* {@link Text} captions, one per row of the data, each centred on its slot
|
|
47
|
-
* beneath the baseline.
|
|
48
|
-
*
|
|
49
|
-
* Not a variant of the line chart's `HorizontalAxis` and deliberately not
|
|
50
|
-
* folded into it: that axis places markers by *value* across a numeric range,
|
|
51
|
-
* this one divides its width into equal slots and centres a name in each. The
|
|
52
|
-
* two look alike on screen and share nothing underneath — one reads a scale,
|
|
53
|
-
* the other counts rows.
|
|
54
|
-
*
|
|
55
|
-
* The slot arithmetic is the same as the plot's, because this node is laid out
|
|
56
|
-
* to exactly the plot's width (the chart reserves the axis gutter with an
|
|
57
|
-
* invisible twin of the value axis, as the line chart does), so a caption lands
|
|
58
|
-
* under the columns it names without either side being told about the other.
|
|
59
|
-
*
|
|
60
|
-
* {@link enter} staggers the captions in left-to-right, each lifted a little
|
|
61
|
-
* above its slot and transparent; the resting state is the landed one, so a
|
|
62
|
-
* chart that is never told to enter still reads as finished.
|
|
63
|
-
*/
|
|
64
|
-
export class CategoryAxis extends Node2D<CategoryAxisProps> {
|
|
65
|
-
@property({ default: () => [] as string[] }) declare categories: string[]
|
|
66
|
-
@property({ default: DEFAULT_X_AXIS }) declare axis: AxisConfig
|
|
67
|
-
@property({ default: "" }) declare label: string
|
|
68
|
-
@property({ default: () => [] as number[] }) declare dims: number[]
|
|
69
|
-
|
|
70
|
-
/** One caption per category, ordered left → right, for the staggered enter. */
|
|
71
|
-
private captionNodes: Text[] = []
|
|
72
|
-
/** The axis title, or null when `label` is empty. */
|
|
73
|
-
private labelNode: Text | null = null
|
|
74
|
-
|
|
75
|
-
/** Centre x of slot `i`, in the node's centred space. */
|
|
76
|
-
private slotCenter(index: number): number {
|
|
77
|
-
const n = this.categories.length
|
|
78
|
-
if (n <= 0) return 0
|
|
79
|
-
const width = this.layoutBounds.width
|
|
80
|
-
return -width / 2 + (width / n) * (index + 0.5)
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
constructor(props?: NodeConfig<CategoryAxis, CategoryAxisProps>) {
|
|
84
|
-
super(props)
|
|
85
|
-
|
|
86
|
-
const tickPad = insetsOps.resolve(this.axis.tickPadding).top
|
|
87
|
-
const titlePad = insetsOps.resolve(this.axis.titlePadding).top
|
|
88
|
-
|
|
89
|
-
// Each caption sits in a hug box carrying the spotlight dim, so the
|
|
90
|
-
// entrance can animate the text's own opacity without the two fighting over
|
|
91
|
-
// one value — opacity multiplies down the tree, which is exactly the
|
|
92
|
-
// composition wanted here.
|
|
93
|
-
const slots = this.categories.map((caption, i) => {
|
|
94
|
-
const text = new Text({
|
|
95
|
-
...textOps.styleProps(this.axis.labelStyle),
|
|
96
|
-
text: caption,
|
|
97
|
-
})
|
|
98
|
-
this.captionNodes.push(text)
|
|
99
|
-
return new Rect({
|
|
100
|
-
width: "hug",
|
|
101
|
-
height: "hug",
|
|
102
|
-
flow: "freeform",
|
|
103
|
-
opacity: () => clampUnit(this.dims[i] ?? 1),
|
|
104
|
-
x: () => this.slotCenter(i),
|
|
105
|
-
children: [text],
|
|
106
|
-
})
|
|
107
|
-
})
|
|
108
|
-
|
|
109
|
-
const children: Node2D[] = [
|
|
110
|
-
new Rect({
|
|
111
|
-
width: "fill",
|
|
112
|
-
height: "hug",
|
|
113
|
-
padding: { top: tickPad },
|
|
114
|
-
children: slots,
|
|
115
|
-
}),
|
|
116
|
-
]
|
|
117
|
-
if (this.label !== "") {
|
|
118
|
-
this.labelNode = new Text({
|
|
119
|
-
...textOps.styleProps(this.axis.titleStyle),
|
|
120
|
-
text: this.label,
|
|
121
|
-
})
|
|
122
|
-
children.push(this.labelNode)
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
this.add(new Rect({ flow: "vertical", gap: titlePad, height: "hug", width: "fill", children }))
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Primes every caption (and the title) at its pre-entrance state: lifted above
|
|
130
|
-
* its slot and transparent. Idempotent, so the chart can arm its whole
|
|
131
|
-
* composition before the first frame is drawn.
|
|
132
|
-
*/
|
|
133
|
-
arm(slide = SLIDE): void {
|
|
134
|
-
for (const caption of this.captionNodes) caption.set({ opacity: 0, y: slide })
|
|
135
|
-
this.labelNode?.set({ opacity: 0, y: slide })
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Slide + fade every caption in from above, staggered left-to-right, then
|
|
140
|
-
* bring the title down behind them.
|
|
141
|
-
*
|
|
142
|
-
* `args.duration` is the **whole** entrance — the stagger and the title are
|
|
143
|
-
* carved out of it rather than added on top. See {@link enterBudget}.
|
|
144
|
-
*
|
|
145
|
-
* `args.data.stagger` is seconds between successive captions (derived when
|
|
146
|
-
* omitted); `args.data.slide` is the starting upward offset in px (node space
|
|
147
|
-
* is y-up, so a positive start slides *down* into place).
|
|
148
|
-
*/
|
|
149
|
-
@command()
|
|
150
|
-
enter(args: CommandArgs<{ stagger?: number; slide?: number }> & { duration: number }): Seekable {
|
|
151
|
-
const { stagger, slide = SLIDE } = args.data ?? {}
|
|
152
|
-
const easing = args.easing ?? easeOut()
|
|
153
|
-
const nodes = this.captionNodes
|
|
154
|
-
if (nodes.length === 0) return hold(args.duration)
|
|
155
|
-
const { step, per, caption } = enterBudget(
|
|
156
|
-
args.duration,
|
|
157
|
-
nodes.length,
|
|
158
|
-
this.labelNode !== null,
|
|
159
|
-
stagger
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
this.arm(slide)
|
|
163
|
-
|
|
164
|
-
// The stagger was `wait(i * step)` inside a generator, so its offsets only
|
|
165
|
-
// existed while it ran. They were always `i * step`; placed, the same
|
|
166
|
-
// entrance can be asked what it looks like partway through.
|
|
167
|
-
const lastCaptionEnds = (nodes.length - 1) * step + per
|
|
168
|
-
return compose([
|
|
169
|
-
...nodes.map((node, i) =>
|
|
170
|
-
at(i * step, node.to({ data: { opacity: 1, y: 0 }, duration: per, easing }))
|
|
171
|
-
),
|
|
172
|
-
...(this.labelNode
|
|
173
|
-
? [at(lastCaptionEnds, this.labelNode.to({ data: { opacity: 1, y: 0 }, duration: caption, easing }))]
|
|
174
|
-
: []),
|
|
175
|
-
])
|
|
176
|
-
}
|
|
177
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
command,
|
|
3
|
+
Node2D,
|
|
4
|
+
Rect,
|
|
5
|
+
Text,
|
|
6
|
+
easeOut,
|
|
7
|
+
property,
|
|
8
|
+
insetsOps,
|
|
9
|
+
textOps,
|
|
10
|
+
type CommandArgs,
|
|
11
|
+
type NodeConfig,
|
|
12
|
+
type Node2DProps,
|
|
13
|
+
} from "@motionscript/sdk"
|
|
14
|
+
|
|
15
|
+
import {
|
|
16
|
+
DEFAULT_X_AXIS,
|
|
17
|
+
clampUnit,
|
|
18
|
+
enterBudget,
|
|
19
|
+
type AxisConfig,
|
|
20
|
+
} from "../kit/shared"
|
|
21
|
+
import { at, compose, hold, type Seekable } from "@motionscript/sdk/component"
|
|
22
|
+
|
|
23
|
+
export interface CategoryAxisProps extends Node2DProps {
|
|
24
|
+
/** One caption per category slot, left to right — the chart's rows, in order. */
|
|
25
|
+
categories: string[]
|
|
26
|
+
/** Caption/title text style and gutters — see {@link AxisConfig}. */
|
|
27
|
+
axis: AxisConfig
|
|
28
|
+
/**
|
|
29
|
+
* Caption drawn centred in the gutter beneath the category row. Empty string
|
|
30
|
+
* (the default) hides it.
|
|
31
|
+
*/
|
|
32
|
+
label: string
|
|
33
|
+
/**
|
|
34
|
+
* Per-category opacity multiplier — how the chart's category spotlight reaches
|
|
35
|
+
* the captions, so the name under a dimmed column dims with it. Missing
|
|
36
|
+
* entries read as 1.
|
|
37
|
+
*/
|
|
38
|
+
dims: number[]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** How far a caption starts above its slot when it enters, in px. */
|
|
42
|
+
const SLIDE = 24
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* The **categorical** horizontal axis of a {@link BarChart}: a row of
|
|
46
|
+
* {@link Text} captions, one per row of the data, each centred on its slot
|
|
47
|
+
* beneath the baseline.
|
|
48
|
+
*
|
|
49
|
+
* Not a variant of the line chart's `HorizontalAxis` and deliberately not
|
|
50
|
+
* folded into it: that axis places markers by *value* across a numeric range,
|
|
51
|
+
* this one divides its width into equal slots and centres a name in each. The
|
|
52
|
+
* two look alike on screen and share nothing underneath — one reads a scale,
|
|
53
|
+
* the other counts rows.
|
|
54
|
+
*
|
|
55
|
+
* The slot arithmetic is the same as the plot's, because this node is laid out
|
|
56
|
+
* to exactly the plot's width (the chart reserves the axis gutter with an
|
|
57
|
+
* invisible twin of the value axis, as the line chart does), so a caption lands
|
|
58
|
+
* under the columns it names without either side being told about the other.
|
|
59
|
+
*
|
|
60
|
+
* {@link enter} staggers the captions in left-to-right, each lifted a little
|
|
61
|
+
* above its slot and transparent; the resting state is the landed one, so a
|
|
62
|
+
* chart that is never told to enter still reads as finished.
|
|
63
|
+
*/
|
|
64
|
+
export class CategoryAxis extends Node2D<CategoryAxisProps> {
|
|
65
|
+
@property({ default: () => [] as string[] }) declare categories: string[]
|
|
66
|
+
@property({ default: DEFAULT_X_AXIS }) declare axis: AxisConfig
|
|
67
|
+
@property({ default: "" }) declare label: string
|
|
68
|
+
@property({ default: () => [] as number[] }) declare dims: number[]
|
|
69
|
+
|
|
70
|
+
/** One caption per category, ordered left → right, for the staggered enter. */
|
|
71
|
+
private captionNodes: Text[] = []
|
|
72
|
+
/** The axis title, or null when `label` is empty. */
|
|
73
|
+
private labelNode: Text | null = null
|
|
74
|
+
|
|
75
|
+
/** Centre x of slot `i`, in the node's centred space. */
|
|
76
|
+
private slotCenter(index: number): number {
|
|
77
|
+
const n = this.categories.length
|
|
78
|
+
if (n <= 0) return 0
|
|
79
|
+
const width = this.layoutBounds.width
|
|
80
|
+
return -width / 2 + (width / n) * (index + 0.5)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
constructor(props?: NodeConfig<CategoryAxis, CategoryAxisProps>) {
|
|
84
|
+
super(props)
|
|
85
|
+
|
|
86
|
+
const tickPad = insetsOps.resolve(this.axis.tickPadding).top
|
|
87
|
+
const titlePad = insetsOps.resolve(this.axis.titlePadding).top
|
|
88
|
+
|
|
89
|
+
// Each caption sits in a hug box carrying the spotlight dim, so the
|
|
90
|
+
// entrance can animate the text's own opacity without the two fighting over
|
|
91
|
+
// one value — opacity multiplies down the tree, which is exactly the
|
|
92
|
+
// composition wanted here.
|
|
93
|
+
const slots = this.categories.map((caption, i) => {
|
|
94
|
+
const text = new Text({
|
|
95
|
+
...textOps.styleProps(this.axis.labelStyle),
|
|
96
|
+
text: caption,
|
|
97
|
+
})
|
|
98
|
+
this.captionNodes.push(text)
|
|
99
|
+
return new Rect({
|
|
100
|
+
width: "hug",
|
|
101
|
+
height: "hug",
|
|
102
|
+
flow: "freeform",
|
|
103
|
+
opacity: () => clampUnit(this.dims[i] ?? 1),
|
|
104
|
+
x: () => this.slotCenter(i),
|
|
105
|
+
children: [text],
|
|
106
|
+
})
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
const children: Node2D[] = [
|
|
110
|
+
new Rect({
|
|
111
|
+
width: "fill",
|
|
112
|
+
height: "hug",
|
|
113
|
+
padding: { top: tickPad },
|
|
114
|
+
children: slots,
|
|
115
|
+
}),
|
|
116
|
+
]
|
|
117
|
+
if (this.label !== "") {
|
|
118
|
+
this.labelNode = new Text({
|
|
119
|
+
...textOps.styleProps(this.axis.titleStyle),
|
|
120
|
+
text: this.label,
|
|
121
|
+
})
|
|
122
|
+
children.push(this.labelNode)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
this.add(new Rect({ flow: "vertical", gap: titlePad, height: "hug", width: "fill", children }))
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Primes every caption (and the title) at its pre-entrance state: lifted above
|
|
130
|
+
* its slot and transparent. Idempotent, so the chart can arm its whole
|
|
131
|
+
* composition before the first frame is drawn.
|
|
132
|
+
*/
|
|
133
|
+
arm(slide = SLIDE): void {
|
|
134
|
+
for (const caption of this.captionNodes) caption.set({ opacity: 0, y: slide })
|
|
135
|
+
this.labelNode?.set({ opacity: 0, y: slide })
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Slide + fade every caption in from above, staggered left-to-right, then
|
|
140
|
+
* bring the title down behind them.
|
|
141
|
+
*
|
|
142
|
+
* `args.duration` is the **whole** entrance — the stagger and the title are
|
|
143
|
+
* carved out of it rather than added on top. See {@link enterBudget}.
|
|
144
|
+
*
|
|
145
|
+
* `args.data.stagger` is seconds between successive captions (derived when
|
|
146
|
+
* omitted); `args.data.slide` is the starting upward offset in px (node space
|
|
147
|
+
* is y-up, so a positive start slides *down* into place).
|
|
148
|
+
*/
|
|
149
|
+
@command()
|
|
150
|
+
enter(args: CommandArgs<{ stagger?: number; slide?: number }> & { duration: number }): Seekable {
|
|
151
|
+
const { stagger, slide = SLIDE } = args.data ?? {}
|
|
152
|
+
const easing = args.easing ?? easeOut()
|
|
153
|
+
const nodes = this.captionNodes
|
|
154
|
+
if (nodes.length === 0) return hold(args.duration)
|
|
155
|
+
const { step, per, caption } = enterBudget(
|
|
156
|
+
args.duration,
|
|
157
|
+
nodes.length,
|
|
158
|
+
this.labelNode !== null,
|
|
159
|
+
stagger
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
this.arm(slide)
|
|
163
|
+
|
|
164
|
+
// The stagger was `wait(i * step)` inside a generator, so its offsets only
|
|
165
|
+
// existed while it ran. They were always `i * step`; placed, the same
|
|
166
|
+
// entrance can be asked what it looks like partway through.
|
|
167
|
+
const lastCaptionEnds = (nodes.length - 1) * step + per
|
|
168
|
+
return compose([
|
|
169
|
+
...nodes.map((node, i) =>
|
|
170
|
+
at(i * step, node.to({ data: { opacity: 1, y: 0 }, duration: per, easing }))
|
|
171
|
+
),
|
|
172
|
+
...(this.labelNode
|
|
173
|
+
? [at(lastCaptionEnds, this.labelNode.to({ data: { opacity: 1, y: 0 }, duration: caption, easing }))]
|
|
174
|
+
: []),
|
|
175
|
+
])
|
|
176
|
+
}
|
|
177
|
+
}
|