chnobli 0.1.10 → 0.1.12
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/LICENSE.md +21 -0
- package/dist/animation/Animation.d.ts +2 -1
- package/dist/animation/Animation.d.ts.map +1 -1
- package/dist/animation/Animation.js +5 -3
- package/dist/animation/Animation.js.map +1 -1
- package/dist/animator/Animator.d.ts +30 -0
- package/dist/animator/Animator.d.ts.map +1 -0
- package/dist/animator/Animator.js +97 -0
- package/dist/animator/Animator.js.map +1 -0
- package/dist/animator/index.d.ts +5 -0
- package/dist/animator/index.d.ts.map +1 -0
- package/dist/animator/index.js +53 -0
- package/dist/animator/index.js.map +1 -0
- package/dist/animator/public.d.ts +16 -0
- package/dist/animator/public.d.ts.map +1 -0
- package/dist/animator/public.js +50 -0
- package/dist/animator/public.js.map +1 -0
- package/dist/chnobli.d.ts +3 -3
- package/dist/chnobli.d.ts.map +1 -1
- package/dist/chnobli.js.map +1 -1
- package/dist/property/ClassProperty.js +1 -1
- package/dist/property/ClassProperty.js.map +1 -1
- package/dist/property/TransformXYProperty.d.ts.map +1 -1
- package/dist/scroll/Scroll.d.ts +24 -3
- package/dist/scroll/Scroll.d.ts.map +1 -1
- package/dist/scroll/Scroll.js +157 -43
- package/dist/scroll/Scroll.js.map +1 -1
- package/dist/scroll/ScrollEvent.d.ts.map +1 -1
- package/dist/scroll/ScrollEvent.js +1 -0
- package/dist/scroll/ScrollEvent.js.map +1 -1
- package/dist/scroll/index.d.ts +2 -0
- package/dist/scroll/index.d.ts.map +1 -1
- package/dist/scroll/index.js +1 -0
- package/dist/scroll/index.js.map +1 -1
- package/dist/scroll/public.d.ts +19 -1
- package/dist/scroll/public.d.ts.map +1 -1
- package/dist/scroll/public.js +26 -1
- package/dist/scroll/public.js.map +1 -1
- package/dist/target/DomTarget.js +1 -1
- package/dist/target/DomTarget.js.map +1 -1
- package/dist/target/ObjectTarget.d.ts +11 -10
- package/dist/target/ObjectTarget.d.ts.map +1 -1
- package/dist/target/ObjectTarget.js +20 -13
- package/dist/target/ObjectTarget.js.map +1 -1
- package/dist/target/TestDomNode.d.ts.map +1 -1
- package/dist/timeline/Timeline.d.ts +2 -1
- package/dist/timeline/Timeline.d.ts.map +1 -1
- package/dist/timeline/Timeline.js +4 -4
- package/dist/timeline/Timeline.js.map +1 -1
- package/dist/timeline/public.d.ts +11 -4
- package/dist/timeline/public.d.ts.map +1 -1
- package/dist/timeline/public.js +19 -11
- package/dist/timeline/public.js.map +1 -1
- package/dist/timing/AnimationFrameTicker.d.ts.map +1 -1
- package/dist/timing/AnimationFrameTicker.js +5 -1
- package/dist/timing/AnimationFrameTicker.js.map +1 -1
- package/dist/timing/TestTicker.d.ts.map +1 -1
- package/dist/timing/TestTicker.js +5 -1
- package/dist/timing/TestTicker.js.map +1 -1
- package/dist/timing/Ticker.d.ts +4 -2
- package/dist/timing/Ticker.d.ts.map +1 -1
- package/dist/timing/Timing.d.ts +47 -2
- package/dist/timing/Timing.d.ts.map +1 -1
- package/dist/timing/Timing.js +118 -84
- package/dist/timing/Timing.js.map +1 -1
- package/dist/timing/easing.d.ts +1 -2
- package/dist/timing/easing.d.ts.map +1 -1
- package/dist/timing/easing.js.map +1 -1
- package/dist/utils/Events.js +1 -1
- package/dist/utils/Events.js.map +1 -1
- package/dist/utils/motionpath.js +5 -5
- package/dist/utils/motionpath.js.map +1 -1
- package/dist/utils/utils.d.ts.map +1 -1
- package/dist/utils/utils.js +0 -8
- package/dist/utils/utils.js.map +1 -1
- package/dist/values/ColorValue.d.ts.map +1 -1
- package/dist/values/ColorValue.js +1 -0
- package/dist/values/ColorValue.js.map +1 -1
- package/dist/values/StyleValue.d.ts.map +1 -1
- package/dist/values/Value.d.ts.map +1 -1
- package/dist/values/Value.js +1 -1
- package/dist/values/Value.js.map +1 -1
- package/eslint.config.js +23 -0
- package/jsr.json +16 -0
- package/package.json +12 -4
- package/src/animation/Animation.ts +6 -3
- package/src/animator/Animator.ts +130 -0
- package/src/animator/index.ts +56 -0
- package/src/animator/public.ts +66 -0
- package/src/chnobli.ts +3 -2
- package/src/property/ClassProperty.ts +1 -1
- package/src/property/TransformXYProperty.ts +1 -1
- package/src/scroll/Scroll.ts +204 -51
- package/src/scroll/ScrollEvent.ts +1 -0
- package/src/scroll/index.ts +3 -0
- package/src/scroll/public.ts +35 -2
- package/src/target/DomTarget.ts +1 -1
- package/src/target/ObjectTarget.ts +19 -13
- package/src/target/TestDomNode.ts +3 -3
- package/src/tests/properties.test.ts +86 -3
- package/src/tests/scroll.test.ts +36 -0
- package/src/tests/timeline.test.ts +1 -1
- package/src/tests/timing.test.ts +32 -0
- package/src/tests/usecases.test.ts +40 -2
- package/src/tests/values.test.ts +9 -9
- package/src/timeline/Timeline.ts +5 -4
- package/src/timeline/public.ts +34 -12
- package/src/timing/AnimationFrameTicker.ts +6 -1
- package/src/timing/TestTicker.ts +7 -1
- package/src/timing/Ticker.ts +5 -1
- package/src/timing/Timing.ts +133 -97
- package/src/timing/easing.ts +6 -1
- package/src/utils/Events.ts +1 -1
- package/src/utils/motionpath.ts +5 -5
- package/src/utils/utils.ts +13 -16
- package/src/values/ColorValue.ts +5 -4
- package/src/values/StyleValue.ts +4 -4
- package/src/values/Value.ts +8 -8
- package/.eslintrc.cjs +0 -39
- package/src/animator.js +0 -187
package/src/scroll/Scroll.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
|
-
import
|
|
1
|
+
import ResponsiveEvent from '../responsive/ResponsiveEvent.js';
|
|
2
|
+
import PublicTimeline from '../timeline/public.js';
|
|
3
|
+
import Events from '../utils/Events.js';
|
|
2
4
|
import { pageOffset } from '../utils/utils.js';
|
|
3
5
|
import ScrollEvent from './ScrollEvent.js';
|
|
4
6
|
|
|
7
|
+
export type DestroyOptions = {
|
|
8
|
+
/// defaults to true
|
|
9
|
+
timelines?: boolean;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
const DEF_DESTROY_OPTS: DestroyOptions = {
|
|
13
|
+
timelines: true,
|
|
14
|
+
};
|
|
15
|
+
|
|
5
16
|
/*
|
|
6
17
|
run timelines based on the scroll position
|
|
7
18
|
|
|
@@ -54,11 +65,13 @@ export type ScrollTrigger =
|
|
|
54
65
|
|
|
55
66
|
export type OffsetValue = 'top' | 'center' | 'bottom' | number;
|
|
56
67
|
|
|
68
|
+
export type State = 'before' | 'in' | 'after';
|
|
69
|
+
|
|
57
70
|
export type ParsedScrollTrigger = {
|
|
58
71
|
target: HTMLElement;
|
|
59
72
|
offset: number;
|
|
60
73
|
view: number;
|
|
61
|
-
position: Position;
|
|
74
|
+
position: Position | undefined;
|
|
62
75
|
};
|
|
63
76
|
|
|
64
77
|
export type ScrollOffset = {
|
|
@@ -72,35 +85,45 @@ export type ScrollOffset = {
|
|
|
72
85
|
|
|
73
86
|
export type Position = number | string;
|
|
74
87
|
|
|
88
|
+
type LastSeek = {
|
|
89
|
+
pos: number;
|
|
90
|
+
state: State;
|
|
91
|
+
};
|
|
92
|
+
|
|
75
93
|
export default class ScrollTimeline {
|
|
76
94
|
private _initialized: boolean;
|
|
77
|
-
private _globalEvent: ScrollEvent;
|
|
78
|
-
private
|
|
95
|
+
private _globalEvent: ScrollEvent | null;
|
|
96
|
+
private _scrollEvent: () => void;
|
|
97
|
+
private _responsiveEvent: any;
|
|
79
98
|
|
|
80
99
|
private _triggers: ParsedScrollTrigger[];
|
|
100
|
+
private _events: Events;
|
|
101
|
+
private lastEvPos: number;
|
|
81
102
|
private timelines: PublicTimeline[];
|
|
103
|
+
private state: State;
|
|
104
|
+
private lastSeek: LastSeek | undefined;
|
|
82
105
|
offsets: ScrollOffset[];
|
|
83
106
|
|
|
107
|
+
private debugMarkers: HTMLElement[];
|
|
108
|
+
private debugPrefix?: string;
|
|
109
|
+
|
|
84
110
|
constructor() {
|
|
85
111
|
this._initialized = false;
|
|
86
112
|
this._globalEvent = ScrollEvent.global();
|
|
87
|
-
this.
|
|
113
|
+
this._scrollEvent =
|
|
114
|
+
this._globalEvent?.add(y => this._onScroll(y)).remove ?? (() => {});
|
|
115
|
+
this._responsiveEvent = ResponsiveEvent.global()?.add((a, b) => {
|
|
116
|
+
this._onResponsive(a, b);
|
|
117
|
+
});
|
|
88
118
|
|
|
89
119
|
this._triggers = [];
|
|
120
|
+
this._events = new Events();
|
|
121
|
+
this.lastEvPos = NaN;
|
|
90
122
|
this.timelines = [];
|
|
123
|
+
this.state = 'in';
|
|
91
124
|
this.offsets = [];
|
|
92
125
|
|
|
93
|
-
|
|
94
|
-
// this._triggers = triggers.map(parseTrigger);
|
|
95
|
-
// this.offsets = this._triggers.map(t => {
|
|
96
|
-
// return {
|
|
97
|
-
// y: 0,
|
|
98
|
-
// view: t.view,
|
|
99
|
-
// };
|
|
100
|
-
// });
|
|
101
|
-
|
|
102
|
-
// if (this.offsets.length < 2)
|
|
103
|
-
// throw new Error('scroll timeline needs at least two triggers');
|
|
126
|
+
this.debugMarkers = [];
|
|
104
127
|
}
|
|
105
128
|
|
|
106
129
|
/**
|
|
@@ -120,21 +143,38 @@ export default class ScrollTimeline {
|
|
|
120
143
|
this.timelines.push(timeline);
|
|
121
144
|
}
|
|
122
145
|
|
|
123
|
-
|
|
146
|
+
on(event: string, fn: (...args: any[]) => void): () => void {
|
|
147
|
+
return this._events.add(event, fn);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/// Returns true if the init function was executed
|
|
151
|
+
init(): boolean {
|
|
152
|
+
if (this._initialized) return false;
|
|
153
|
+
|
|
154
|
+
this._initialized = true;
|
|
155
|
+
|
|
124
156
|
// todo we need to calculate the position for each timeline
|
|
125
157
|
//
|
|
126
158
|
// calculate the positions and offsets
|
|
127
159
|
// if we are missing one extend them
|
|
128
160
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
this.offsets = this._triggers.map(t => {
|
|
132
|
-
const offset = pageOffset(t.target);
|
|
161
|
+
if (this._triggers.length < 1)
|
|
162
|
+
throw new Error('scroll timeline needs at least one trigger');
|
|
133
163
|
|
|
134
|
-
|
|
164
|
+
if (this._triggers.length === 1) {
|
|
165
|
+
this._triggers.push({
|
|
166
|
+
target: this._triggers[0].target,
|
|
167
|
+
offset: 1,
|
|
168
|
+
view: 1,
|
|
169
|
+
position: 1,
|
|
170
|
+
});
|
|
171
|
+
}
|
|
135
172
|
|
|
136
|
-
|
|
173
|
+
const positionStep = 1 / (this._triggers.length - 1);
|
|
137
174
|
|
|
175
|
+
// first calculate position and view
|
|
176
|
+
let prevPos = 0;
|
|
177
|
+
this.offsets = this._triggers.map((t, i) => {
|
|
138
178
|
let position;
|
|
139
179
|
if (typeof t.position === 'string') {
|
|
140
180
|
if (this.timelines.length !== 1)
|
|
@@ -143,59 +183,172 @@ export default class ScrollTimeline {
|
|
|
143
183
|
);
|
|
144
184
|
|
|
145
185
|
position = this.timelines[0].labelPosition(t.position);
|
|
146
|
-
} else if (
|
|
186
|
+
} else if (typeof t.position === 'number') {
|
|
147
187
|
position = t.position;
|
|
148
188
|
} else {
|
|
149
|
-
|
|
189
|
+
position = i * positionStep;
|
|
150
190
|
}
|
|
151
191
|
|
|
192
|
+
if (position < prevPos)
|
|
193
|
+
throw new Error('positions are not in order');
|
|
194
|
+
prevPos = position;
|
|
195
|
+
|
|
152
196
|
return {
|
|
153
|
-
y,
|
|
197
|
+
y: 0,
|
|
154
198
|
view: t.view,
|
|
155
199
|
position,
|
|
156
200
|
};
|
|
157
201
|
});
|
|
158
202
|
|
|
159
|
-
|
|
160
|
-
throw new Error('scroll timeline needs at least one trigger');
|
|
203
|
+
this.initY();
|
|
161
204
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
private initY() {
|
|
209
|
+
let previousY = -1;
|
|
210
|
+
this.offsets.forEach((offset, i) => {
|
|
211
|
+
const t = this._triggers[i];
|
|
212
|
+
|
|
213
|
+
const pOffset = pageOffset(t.target);
|
|
214
|
+
const y = pOffset.top + pOffset.height * t.offset;
|
|
215
|
+
|
|
216
|
+
if (y < previousY) throw new Error('offsets are not in order');
|
|
217
|
+
previousY = y;
|
|
218
|
+
|
|
219
|
+
offset.y = y;
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
update() {
|
|
224
|
+
// execute initY to check if elements have moved
|
|
225
|
+
if (!this.init()) this.initY();
|
|
226
|
+
|
|
227
|
+
// todo this position should come from the GlobalEvent
|
|
228
|
+
this._onScroll({
|
|
229
|
+
y: window.scrollY,
|
|
230
|
+
height: window.innerHeight,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
destroy(opts: DestroyOptions = {}) {
|
|
235
|
+
opts = { ...DEF_DESTROY_OPTS, ...opts };
|
|
236
|
+
|
|
237
|
+
this._scrollEvent();
|
|
238
|
+
this._events.destroy();
|
|
239
|
+
this._responsiveEvent?.remove();
|
|
240
|
+
|
|
241
|
+
if (opts.timelines) {
|
|
242
|
+
for (const timeline of this.timelines) {
|
|
243
|
+
timeline.destroy();
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
for (const marker of this.debugMarkers) {
|
|
248
|
+
marker.remove();
|
|
170
249
|
}
|
|
250
|
+
this.debugMarkers = [];
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
debug(prefix?: string) {
|
|
254
|
+
this.init();
|
|
255
|
+
|
|
256
|
+
this.debugPrefix = prefix;
|
|
257
|
+
|
|
258
|
+
const height = window.innerHeight;
|
|
259
|
+
|
|
260
|
+
this.offsets.forEach((offset, i) => {
|
|
261
|
+
const y = offset.y - height * offset.view;
|
|
262
|
+
|
|
263
|
+
const marker = document.createElement('span');
|
|
264
|
+
marker.textContent =
|
|
265
|
+
(prefix ? prefix + ' ' : '') + i + ': ' + offset.position;
|
|
266
|
+
marker.style.position = 'absolute';
|
|
267
|
+
marker.style.display = 'block';
|
|
268
|
+
marker.style.right = '0';
|
|
269
|
+
marker.style.top = y + 'px';
|
|
270
|
+
marker.style.minWidth = '50px';
|
|
271
|
+
marker.style.height = '2px';
|
|
272
|
+
marker.style.paddingRight = '10px';
|
|
273
|
+
marker.style.backgroundColor = 'red';
|
|
274
|
+
marker.style.zIndex = '100000';
|
|
275
|
+
|
|
276
|
+
document.body.appendChild(marker);
|
|
277
|
+
this.debugMarkers.push(marker);
|
|
278
|
+
});
|
|
171
279
|
}
|
|
172
280
|
|
|
173
281
|
private _onScroll({ y, height }: { y: number; height: number }) {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
282
|
+
this.init();
|
|
283
|
+
|
|
284
|
+
const pos = this.calcPosition({ y, height });
|
|
285
|
+
const clampPos = Math.min(1, Math.max(0, pos));
|
|
286
|
+
const state = pos < 0 ? 'before' : pos > 1 ? 'after' : 'in';
|
|
287
|
+
|
|
288
|
+
// we need to trigger once
|
|
289
|
+
// if the pos is not the same and but pos can have 3 states
|
|
290
|
+
// under (<0), in (0-1) or over (>1)
|
|
291
|
+
// each state should be triggered once
|
|
292
|
+
if (this.lastSeek?.pos === clampPos && this.lastSeek?.state === state) {
|
|
293
|
+
return;
|
|
177
294
|
}
|
|
178
295
|
|
|
296
|
+
this.lastSeek = { pos: clampPos, state };
|
|
297
|
+
|
|
298
|
+
this._events.trigger('update', clampPos, state);
|
|
299
|
+
|
|
300
|
+
for (const timeline of this.timelines) {
|
|
301
|
+
timeline.seek(pos);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* @ignore
|
|
307
|
+
*/
|
|
308
|
+
private _onResponsive(
|
|
309
|
+
_a: { width: number; height: number },
|
|
310
|
+
_b: { remove: () => void },
|
|
311
|
+
) {
|
|
312
|
+
this.update();
|
|
313
|
+
|
|
314
|
+
// reposition debug Markers
|
|
315
|
+
if (this.debugMarkers.length) {
|
|
316
|
+
for (const marker of this.debugMarkers) {
|
|
317
|
+
marker.remove();
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
this.debug(this.debugPrefix);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
private calcPosition({ y, height }: { y: number; height: number }): number {
|
|
325
|
+
// check if it's outside of the bounds
|
|
326
|
+
const first = this.offsets[0];
|
|
327
|
+
if (y < first.y - height * first.view) return -1;
|
|
328
|
+
|
|
329
|
+
const last = this.offsets[this.offsets.length - 1];
|
|
330
|
+
if (y > last.y - height * last.view) return 2;
|
|
331
|
+
|
|
179
332
|
// find the matching offset
|
|
180
333
|
// rolling window
|
|
181
334
|
for (let i = 1; i < this.offsets.length; i++) {
|
|
182
335
|
const start = this.offsets[i - 1];
|
|
183
336
|
const end = this.offsets[i];
|
|
184
337
|
|
|
185
|
-
const startY = start.y
|
|
186
|
-
const endY = end.y
|
|
187
|
-
|
|
188
|
-
const dif = endY - startY;
|
|
189
|
-
const x = 1 - (endY - y) / dif;
|
|
338
|
+
const startY = start.y - height * start.view;
|
|
339
|
+
const endY = end.y - height * end.view;
|
|
190
340
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
341
|
+
// the end is included, at the bottom of the page y can't get
|
|
342
|
+
// past the last offset
|
|
343
|
+
if (y >= startY && y <= endY) {
|
|
344
|
+
const dif = endY - startY;
|
|
345
|
+
const x = dif === 0 ? 1 : 1 - (endY - y) / dif;
|
|
195
346
|
|
|
196
|
-
|
|
347
|
+
return start.position + (end.position - start.position) * x;
|
|
197
348
|
}
|
|
198
349
|
}
|
|
350
|
+
|
|
351
|
+
return -1;
|
|
199
352
|
}
|
|
200
353
|
}
|
|
201
354
|
|
|
@@ -239,7 +392,7 @@ function parseTrigger(
|
|
|
239
392
|
target: element,
|
|
240
393
|
offset: parseOffset(offset),
|
|
241
394
|
view: parseOffset(view),
|
|
242
|
-
position
|
|
395
|
+
position,
|
|
243
396
|
};
|
|
244
397
|
}
|
|
245
398
|
|
|
@@ -261,7 +414,7 @@ function parseOffset(val: OffsetValue): number {
|
|
|
261
414
|
throw new Error('unknown view value ' + val);
|
|
262
415
|
}
|
|
263
416
|
|
|
264
|
-
if (typeof val !== 'number'
|
|
417
|
+
if (typeof val !== 'number') {
|
|
265
418
|
throw new Error(
|
|
266
419
|
'view expecting to be a top/center/bottom or a percent value',
|
|
267
420
|
);
|
package/src/scroll/index.ts
CHANGED
package/src/scroll/public.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { Timeline } from '../chnobli.js';
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
import ScrollTimeline, {
|
|
3
|
+
DestroyOptions,
|
|
4
|
+
Position,
|
|
5
|
+
ScrollTrigger,
|
|
6
|
+
} from './Scroll.js';
|
|
4
7
|
|
|
5
8
|
export default class Scroll {
|
|
6
9
|
private _inner: ScrollTimeline;
|
|
@@ -28,4 +31,34 @@ export default class Scroll {
|
|
|
28
31
|
|
|
29
32
|
return this;
|
|
30
33
|
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Listen on events
|
|
37
|
+
*
|
|
38
|
+
* returns a function to remove the event listener
|
|
39
|
+
*
|
|
40
|
+
* ## Events
|
|
41
|
+
*
|
|
42
|
+
* ### Update
|
|
43
|
+
* The scroll position has been updated passes in a number between 0 and 1
|
|
44
|
+
*
|
|
45
|
+
*/
|
|
46
|
+
on(event: string, fn: (...args: any[]) => void): () => void {
|
|
47
|
+
return this._inner.on(event, fn);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
update() {
|
|
51
|
+
this._inner.update();
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Destroy the scroll
|
|
56
|
+
*/
|
|
57
|
+
destroy(opts: DestroyOptions = {}) {
|
|
58
|
+
this._inner.destroy(opts);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
debug(prefix?: string) {
|
|
62
|
+
this._inner.debug(prefix);
|
|
63
|
+
}
|
|
31
64
|
}
|
package/src/target/DomTarget.ts
CHANGED
|
@@ -9,6 +9,7 @@ export default class ObjectTarget implements Target {
|
|
|
9
9
|
|
|
10
10
|
// private transformValues: Map<string, (Value | null)[]>;
|
|
11
11
|
private styleValues: Map<string, StyleValue | undefined>;
|
|
12
|
+
private firstValues: Map<string, StyleValue | undefined>;
|
|
12
13
|
// private values: Map<string, Value>;
|
|
13
14
|
|
|
14
15
|
/**
|
|
@@ -20,6 +21,7 @@ export default class ObjectTarget implements Target {
|
|
|
20
21
|
this.target = target;
|
|
21
22
|
|
|
22
23
|
this.styleValues = new Map();
|
|
24
|
+
this.firstValues = new Map();
|
|
23
25
|
// this.values = new Map();
|
|
24
26
|
}
|
|
25
27
|
|
|
@@ -31,30 +33,30 @@ export default class ObjectTarget implements Target {
|
|
|
31
33
|
return 'object';
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
getValue(
|
|
36
|
+
getValue(_name: string): Value | null {
|
|
35
37
|
// return this.values.get(name) ?? null;
|
|
36
38
|
throw new Error('not supported');
|
|
37
39
|
}
|
|
38
40
|
|
|
39
|
-
setValue(
|
|
41
|
+
setValue(_name: string, _value: Value) {
|
|
40
42
|
// this.values.set(name, value);
|
|
41
43
|
throw new Error('not supported');
|
|
42
44
|
}
|
|
43
45
|
|
|
44
|
-
removeValue(
|
|
46
|
+
removeValue(_name: string) {
|
|
45
47
|
// this.values.delete(name);
|
|
46
48
|
throw new Error('not supported');
|
|
47
49
|
}
|
|
48
50
|
|
|
49
|
-
getTransformValue(
|
|
51
|
+
getTransformValue(_name: string): Value | null {
|
|
50
52
|
throw new Error('not supported');
|
|
51
53
|
}
|
|
52
54
|
|
|
53
|
-
setTransformValue(
|
|
55
|
+
setTransformValue(_name: string, _value: Value) {
|
|
54
56
|
throw new Error('not supported');
|
|
55
57
|
}
|
|
56
58
|
|
|
57
|
-
removeTransformValue(
|
|
59
|
+
removeTransformValue(_name: string) {
|
|
58
60
|
throw new Error('not supported');
|
|
59
61
|
}
|
|
60
62
|
|
|
@@ -71,6 +73,7 @@ export default class ObjectTarget implements Target {
|
|
|
71
73
|
try {
|
|
72
74
|
const value = StyleValue.parse(styleV);
|
|
73
75
|
this.styleValues.set(name, value);
|
|
76
|
+
this.firstValues.set(name, value);
|
|
74
77
|
|
|
75
78
|
return value;
|
|
76
79
|
} catch (e) {
|
|
@@ -87,19 +90,19 @@ export default class ObjectTarget implements Target {
|
|
|
87
90
|
this.styleValues.set(name, undefined);
|
|
88
91
|
}
|
|
89
92
|
|
|
90
|
-
hasClass(
|
|
93
|
+
hasClass(_name: string): boolean {
|
|
91
94
|
throw new Error('not supported');
|
|
92
95
|
}
|
|
93
96
|
|
|
94
|
-
addClass(
|
|
97
|
+
addClass(_name: string): void {
|
|
95
98
|
throw new Error('not supported');
|
|
96
99
|
}
|
|
97
100
|
|
|
98
|
-
removeClass(
|
|
101
|
+
removeClass(_name: string): void {
|
|
99
102
|
throw new Error('not supported');
|
|
100
103
|
}
|
|
101
104
|
|
|
102
|
-
unifyValues(
|
|
105
|
+
unifyValues(_name: string, a: Value, b: Value): [Value, Value] {
|
|
103
106
|
if (a.unit === b.unit) return [a, b];
|
|
104
107
|
|
|
105
108
|
if (!a.unit && b.unit) a.unit = b.unit;
|
|
@@ -113,9 +116,12 @@ export default class ObjectTarget implements Target {
|
|
|
113
116
|
// style
|
|
114
117
|
for (const [k, v] of this.styleValues.entries()) {
|
|
115
118
|
if (v === undefined) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
+
const first = this.firstValues.get(k);
|
|
120
|
+
if (typeof first !== 'undefined') {
|
|
121
|
+
this.target[k] = first.toMixed();
|
|
122
|
+
} else {
|
|
123
|
+
delete this.target[k];
|
|
124
|
+
}
|
|
119
125
|
} else {
|
|
120
126
|
this.target[k] = v.toMixed();
|
|
121
127
|
}
|
|
@@ -45,11 +45,11 @@ export default class TestDomNode {
|
|
|
45
45
|
|
|
46
46
|
__simulatedDom__() {}
|
|
47
47
|
|
|
48
|
-
__getComputedStyleFn__() {
|
|
48
|
+
__getComputedStyleFn__(): typeof TestDomNode.getComputedStyle {
|
|
49
49
|
return TestDomNode.getComputedStyle;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
__getRootElementFn__() {
|
|
52
|
+
__getRootElementFn__(): typeof getRootElement {
|
|
53
53
|
return getRootElement;
|
|
54
54
|
}
|
|
55
55
|
}
|
|
@@ -58,7 +58,7 @@ export function el() {
|
|
|
58
58
|
return new TestDomNode();
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
-
export function getRootElement() {
|
|
61
|
+
export function getRootElement(): TestDomNode {
|
|
62
62
|
if (!ROOT_ELEMENT) ROOT_ELEMENT = el();
|
|
63
63
|
return ROOT_ELEMENT;
|
|
64
64
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { describe, expect, it } from 'vitest';
|
|
2
2
|
import TestTicker from '../timing/TestTicker.js';
|
|
3
3
|
import TestResponsiveEvent from '../responsive/TestEvent.js';
|
|
4
|
-
import {
|
|
4
|
+
import { timeline } from '../chnobli.js';
|
|
5
5
|
import { responsive, curve, fromTo } from '../utils/utils.js';
|
|
6
6
|
import { el } from '../target/TestDomNode.js';
|
|
7
7
|
import { timeout } from 'fire/utils';
|
|
@@ -60,7 +60,7 @@ describe('properties', () => {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
let resolveCleanupProm: any;
|
|
63
|
-
|
|
63
|
+
const cleanupProm = new Promise(
|
|
64
64
|
resolve => (resolveCleanupProm = resolve),
|
|
65
65
|
);
|
|
66
66
|
const cleanup = new FinalizationRegistry(key => {
|
|
@@ -79,6 +79,47 @@ describe('properties', () => {
|
|
|
79
79
|
expect(res).toBe('div');
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
+
it('keep values', () => {
|
|
83
|
+
const ticker = new TestTicker();
|
|
84
|
+
|
|
85
|
+
const div = el();
|
|
86
|
+
const tl = timeline()
|
|
87
|
+
.add(div, {
|
|
88
|
+
x: 100,
|
|
89
|
+
duration: 10,
|
|
90
|
+
})
|
|
91
|
+
.play();
|
|
92
|
+
|
|
93
|
+
ticker.run(5);
|
|
94
|
+
expect(div.style.transform).toBe(
|
|
95
|
+
'translate3d(50.000px,0.000px,0.000px)',
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
tl.destroy({ keepValues: true });
|
|
99
|
+
expect(div.style.transform).toBe(
|
|
100
|
+
'translate3d(50.000px,0.000px,0.000px)',
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const tl2 = timeline()
|
|
104
|
+
.add(div, {
|
|
105
|
+
x: 100,
|
|
106
|
+
duration: 10,
|
|
107
|
+
})
|
|
108
|
+
.play();
|
|
109
|
+
expect(div.style.transform).toBe(
|
|
110
|
+
'translate3d(50.000px,0.000px,0.000px)',
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
ticker.run();
|
|
114
|
+
expect(div.style.transform).toBe(
|
|
115
|
+
'translate3d(100.000px,0.000px,0.000px)',
|
|
116
|
+
);
|
|
117
|
+
tl2.destroy({ keepValues: true });
|
|
118
|
+
expect(div.style.transform).toBe(
|
|
119
|
+
'translate3d(100.000px,0.000px,0.000px)',
|
|
120
|
+
);
|
|
121
|
+
});
|
|
122
|
+
|
|
82
123
|
it('update timeline', () => {
|
|
83
124
|
const ticker = new TestTicker();
|
|
84
125
|
const respEv = new TestResponsiveEvent();
|
|
@@ -206,7 +247,7 @@ describe('properties', () => {
|
|
|
206
247
|
tl.reverse();
|
|
207
248
|
tl.play();
|
|
208
249
|
ticker.run();
|
|
209
|
-
expect(obj.x).toBe(
|
|
250
|
+
expect(obj.x).toBe(0);
|
|
210
251
|
expect(obj.width).toBe(undefined);
|
|
211
252
|
});
|
|
212
253
|
|
|
@@ -230,4 +271,46 @@ describe('properties', () => {
|
|
|
230
271
|
ticker.run();
|
|
231
272
|
expect(div.style.width).toBe(undefined);
|
|
232
273
|
});
|
|
274
|
+
|
|
275
|
+
// fails until #7 is fixed
|
|
276
|
+
it.fails('restore before', () => {
|
|
277
|
+
const ticker = new TestTicker();
|
|
278
|
+
|
|
279
|
+
const div = el();
|
|
280
|
+
const tl = timeline().add(div, {
|
|
281
|
+
x: 100,
|
|
282
|
+
duration: 10,
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
tl.seek(0.95);
|
|
286
|
+
|
|
287
|
+
ticker.run();
|
|
288
|
+
expect(div.style.transform).toBe(
|
|
289
|
+
'translate3d(95.000px,0.000px,0.000px)',
|
|
290
|
+
);
|
|
291
|
+
|
|
292
|
+
const tl2 = timeline().add(div, {
|
|
293
|
+
x: 100,
|
|
294
|
+
duration: 10,
|
|
295
|
+
});
|
|
296
|
+
tl2._inner.init();
|
|
297
|
+
|
|
298
|
+
ticker.run();
|
|
299
|
+
expect(div.style.transform).toBe(
|
|
300
|
+
'translate3d(95.000px,0.000px,0.000px)',
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
timeline()
|
|
304
|
+
.add(
|
|
305
|
+
{ opacity: 0 },
|
|
306
|
+
{
|
|
307
|
+
opacity: 1,
|
|
308
|
+
},
|
|
309
|
+
)
|
|
310
|
+
.play();
|
|
311
|
+
ticker.run();
|
|
312
|
+
expect(div.style.transform).toBe(
|
|
313
|
+
'translate3d(95.000px,0.000px,0.000px)',
|
|
314
|
+
);
|
|
315
|
+
});
|
|
233
316
|
});
|