pacer-js 1.0.4 → 1.0.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/Pacer.js +73 -27
- package/README.md +69 -7
- package/package.json +1 -1
package/Pacer.js
CHANGED
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
|
|
23
23
|
isUsefulNumber,
|
|
24
24
|
isNotUsefulNumber,
|
|
25
|
+
isUsefulString,
|
|
25
26
|
normalize,
|
|
26
27
|
normalize01,
|
|
27
28
|
lerp
|
|
@@ -33,11 +34,13 @@ import {
|
|
|
33
34
|
|
|
34
35
|
class Key {
|
|
35
36
|
|
|
36
|
-
constructor( timeAbsolute, values ){
|
|
37
|
+
constructor( timeAbsolute, values, callback ){
|
|
37
38
|
|
|
38
39
|
this.timeAbsolute = timeAbsolute
|
|
39
40
|
this.values = values instanceof Object ? values : {}
|
|
41
|
+
this.onKey = callback
|
|
40
42
|
this.tween = Pacer.linear// Default tween method is linear interpolation.
|
|
43
|
+
this.label = ''
|
|
41
44
|
this.guarantee = true
|
|
42
45
|
}
|
|
43
46
|
}
|
|
@@ -47,10 +50,10 @@ class Key {
|
|
|
47
50
|
|
|
48
51
|
class Pacer {
|
|
49
52
|
|
|
50
|
-
constructor( label ){
|
|
53
|
+
constructor( label, units ){
|
|
51
54
|
|
|
52
|
-
this._label = label
|
|
53
|
-
this.
|
|
55
|
+
this._label = isUsefulString( label ) ? label : 'Untitled Pacer instance'
|
|
56
|
+
this._units = isUsefulString( units ) ? units : 'ms'// ms, milliseconds, s, seconds, #, n, norm, normalize, normalized, %, percent
|
|
54
57
|
|
|
55
58
|
this.keys = []
|
|
56
59
|
this.keyIndex = -1
|
|
@@ -60,9 +63,9 @@ class Pacer {
|
|
|
60
63
|
this.n = 0
|
|
61
64
|
this.direction = 1
|
|
62
65
|
this.isClamped = true
|
|
63
|
-
|
|
64
|
-
this.instanceIndex = Pacer.all.length
|
|
66
|
+
|
|
65
67
|
this.isEnabled = true
|
|
68
|
+
this.instanceIndex = Pacer.all.length
|
|
66
69
|
Pacer.all.push( this )
|
|
67
70
|
}
|
|
68
71
|
|
|
@@ -71,17 +74,30 @@ class Pacer {
|
|
|
71
74
|
|
|
72
75
|
// Non-chainable.
|
|
73
76
|
|
|
74
|
-
inspect(){
|
|
77
|
+
inspect( useRelative ){
|
|
75
78
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
const scope = this
|
|
80
|
+
let out = ''
|
|
81
|
+
out += '\n'+ this._label
|
|
82
|
+
out += '\n'+ new Array( this._label.length ).fill( '─' ).join( '' )
|
|
83
|
+
out += this.keys
|
|
79
84
|
.reduce( function( output, key ){
|
|
80
85
|
|
|
86
|
+
output += '\n'
|
|
87
|
+
output += useRelative === true && isUsefulNumber( key.timeRelative )
|
|
88
|
+
? ' +'+ key.timeRelative
|
|
89
|
+
: ' '+ key.timeAbsolute
|
|
90
|
+
output += scope._units +' '
|
|
91
|
+
if( isUsefulString( key.label )) output += key.label +' '
|
|
92
|
+
output += JSON.stringify( key.values )
|
|
93
|
+
return output
|
|
94
|
+
|
|
95
|
+
}, '' )
|
|
81
96
|
|
|
82
|
-
return output +'\n'+ key.timeAbsolute +' '+ JSON.stringify( key.values )
|
|
83
97
|
|
|
84
|
-
|
|
98
|
+
// Should add things like timeCursor, total n, etc.
|
|
99
|
+
|
|
100
|
+
return out +'\n\n'
|
|
85
101
|
}
|
|
86
102
|
getFirstKey(){
|
|
87
103
|
|
|
@@ -192,7 +208,7 @@ class Pacer {
|
|
|
192
208
|
this.setTimeBounds()
|
|
193
209
|
return this
|
|
194
210
|
}
|
|
195
|
-
key( time, values, isAbsolute ){
|
|
211
|
+
key( time, values, callback, isAbsolute ){
|
|
196
212
|
|
|
197
213
|
if( isAbsolute !== true &&// Making a theoretical `isRelative` the default for backwards compatibility.
|
|
198
214
|
this.keys.length > 0 ){
|
|
@@ -200,44 +216,74 @@ class Pacer {
|
|
|
200
216
|
time += this.getLastKey().timeAbsolute
|
|
201
217
|
}
|
|
202
218
|
if( this.keys.length === 0 ) this.values = values
|
|
203
|
-
const key = new Key( time, values )
|
|
219
|
+
const key = new Key( time, values, callback )
|
|
204
220
|
this.lastTouchedKey = key
|
|
205
221
|
this.keys.push( key )
|
|
206
222
|
this.sortKeys()
|
|
207
223
|
if( this.keys.length === 1 ) this.timeCursor = this.timeStart - 1
|
|
208
224
|
return this
|
|
209
225
|
}
|
|
210
|
-
rel( timeRelative, values ){
|
|
226
|
+
rel( timeRelative, values, callback ){
|
|
227
|
+
|
|
228
|
+
return this.key( timeRelative, values, callback, false )
|
|
229
|
+
}
|
|
230
|
+
abs( timeAbsolute, values, callback ){
|
|
231
|
+
|
|
232
|
+
return this.key( timeAbsolute, values, callback, true )
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
labelPacer( s ){
|
|
237
|
+
|
|
238
|
+
this._label = s
|
|
239
|
+
return this
|
|
240
|
+
}
|
|
241
|
+
label( s ){
|
|
211
242
|
|
|
212
|
-
|
|
243
|
+
this.lastTouchedKey.label = s
|
|
244
|
+
return this
|
|
213
245
|
}
|
|
214
|
-
|
|
246
|
+
values( v ){
|
|
215
247
|
|
|
216
|
-
|
|
248
|
+
this.lastTouchedKey.values = v
|
|
249
|
+
return this
|
|
217
250
|
}
|
|
218
251
|
tween( fn ){
|
|
219
252
|
|
|
220
253
|
this.lastTouchedKey.tween = fn
|
|
221
254
|
return this
|
|
222
255
|
}
|
|
223
|
-
|
|
256
|
+
clamp(){
|
|
224
257
|
|
|
225
|
-
this.
|
|
258
|
+
this.isClamped = true
|
|
226
259
|
return this
|
|
227
260
|
}
|
|
261
|
+
unclamp(){
|
|
262
|
+
|
|
263
|
+
|
|
264
|
+
this.isClamped = false
|
|
265
|
+
return this
|
|
266
|
+
}
|
|
267
|
+
units( u ){
|
|
268
|
+
|
|
269
|
+
this._units = u
|
|
270
|
+
return this
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
|
|
228
274
|
onKey( fn ){
|
|
229
275
|
|
|
230
|
-
this.lastTouchedKey.
|
|
276
|
+
this.lastTouchedKey.onKey = fn
|
|
231
277
|
return this
|
|
232
278
|
}
|
|
233
279
|
onTween( fn ){
|
|
234
280
|
|
|
235
|
-
this.lastTouchedKey.
|
|
281
|
+
this.lastTouchedKey.onTween = fn
|
|
236
282
|
return this
|
|
237
283
|
}
|
|
238
284
|
onCancel( fn ){
|
|
239
285
|
|
|
240
|
-
this.lastTouchedKey.
|
|
286
|
+
this.lastTouchedKey.onCancel = fn
|
|
241
287
|
return this
|
|
242
288
|
}
|
|
243
289
|
|
|
@@ -415,9 +461,9 @@ class Pacer {
|
|
|
415
461
|
if( tempKey instanceof Key &&
|
|
416
462
|
tempKey.guarantee === true ){
|
|
417
463
|
|
|
418
|
-
if( typeof tempKey.
|
|
464
|
+
if( typeof tempKey.onKey === 'function' ){
|
|
419
465
|
|
|
420
|
-
tempKey.
|
|
466
|
+
tempKey.onKey( tempKey.values, this )
|
|
421
467
|
}
|
|
422
468
|
if( typeof this._onEveryKey === 'function' ){
|
|
423
469
|
|
|
@@ -440,9 +486,9 @@ class Pacer {
|
|
|
440
486
|
if( tempKey instanceof Key &&
|
|
441
487
|
tempKey.guarantee === true ){
|
|
442
488
|
|
|
443
|
-
if( typeof tempKey.
|
|
489
|
+
if( typeof tempKey.onKey === 'function' ){
|
|
444
490
|
|
|
445
|
-
tempKey.
|
|
491
|
+
tempKey.onKey( tempKey.values, this )
|
|
446
492
|
}
|
|
447
493
|
if( typeof this._onEveryKey === 'function' ){
|
|
448
494
|
|
package/README.md
CHANGED
|
@@ -21,7 +21,7 @@ Getting you from A to B since 2025.
|
|
|
21
21
|
|
|
22
22
|
## TL;DR
|
|
23
23
|
|
|
24
|
-
__Pacer__ is a light-weight keyframing toolkit inspired by [Soledad Penadés](https://soledadpenades.com/)’ original [tween.js](https://soledadpenades.com/projects/tween-js/) masterpiece. List your keyframes as time / value pairs, and __Pacer__ will ✨ tween your numbers and 📞 call your callbacks. __It’s minimal__. Only does what it needs to. __It’s reliable__. We use this in our own professional projects. We found the bumps and sanded them down so you won’t have to ✔️ Either include the `Pacer.js` ES6 module in your codebase, or install the Node package:
|
|
24
|
+
__Pacer__ is a light-weight keyframing toolkit inspired by [Soledad Penadés](https://soledadpenades.com/)’ original [tween.js](https://soledadpenades.com/projects/tween-js/) masterpiece. List your keyframes as time / value pairs, and __Pacer__ will ✨ tween your numbers and 📞 call your callbacks. __It’s minimal__. Only does what it needs to. __It’s reliable__. We use this in our own professional projects. We found the bumps and sanded them down so you won’t have to ✔️ Either include the `Pacer.js` ES6 module in your codebase, or install the [Node package](https://www.npmjs.com/package/pacer-js):
|
|
25
25
|
|
|
26
26
|
```shell
|
|
27
27
|
npm install pacer-js
|
|
@@ -367,7 +367,11 @@ As you’d hope, __Pacer__ will also call `onEveryKey` when it honors `onKey` fo
|
|
|
367
367
|
|
|
368
368
|
### Outside the box
|
|
369
369
|
|
|
370
|
-
What happens outside of your declared keyframes?
|
|
370
|
+
What happens outside of your declared keyframes? Nothing. Until you do this with your __Pacer__ instance:
|
|
371
|
+
```javascript
|
|
372
|
+
p.unclamp()
|
|
373
|
+
```
|
|
374
|
+
When your __Pacer__ instance is unclamped, it will automatically extrapolate your first and last tweens forward and backward in time, beyond your declared timeline of keyframes. You often don’t need this—but when you do, you do. Let’s say you have two keyframes, __A__ at time __0__, and __B__ at time __2__. They’re tweening a value, `n`, from `0` to `1` using the default linear interpolation easing function. As a result you can see that at time __1__, the tweened value of `n` will be `0.5`—halfway between its keyframed values of `0` and `1`. So far so good?
|
|
371
375
|
|
|
372
376
|
|
|
373
377
|
```
|
|
@@ -440,11 +444,31 @@ Let’s cram in a bunch of different feature highlights into this one verbose ex
|
|
|
440
444
|
|
|
441
445
|
```javascript
|
|
442
446
|
// We’ll start off with the basics.
|
|
447
|
+
|
|
443
448
|
// Did you know you can label a Pacer instance
|
|
444
449
|
// by passing it a String?
|
|
445
450
|
// That’s useful for debugging later.
|
|
446
451
|
|
|
447
|
-
|
|
452
|
+
// We can also optionally declare our time unit.
|
|
453
|
+
// Let’s use “s” for “seconds.”
|
|
454
|
+
|
|
455
|
+
var p = new Pacer( 'My first Pacer', 's' )
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
// Actually, I lied.
|
|
459
|
+
// This is my SECOND Pacer instance ever.
|
|
460
|
+
// Let’s correct that:
|
|
461
|
+
|
|
462
|
+
.labelPacer( 'My SECOND Pacer' )
|
|
463
|
+
|
|
464
|
+
|
|
465
|
+
// And, oops--we’re using milliseconds.
|
|
466
|
+
// Either way would be fine,
|
|
467
|
+
// as Pacer doesn’t care what units you use.
|
|
468
|
+
// This is more for inspection / debugging,
|
|
469
|
+
// and human reasoning around more complex Pacers.
|
|
470
|
+
|
|
471
|
+
.units( 'ms' )
|
|
448
472
|
|
|
449
473
|
|
|
450
474
|
// Three keyframes, alike in dignity.
|
|
@@ -466,13 +490,13 @@ var p = new Pacer( 'My first Pacer' )
|
|
|
466
490
|
// Now let’s have some fun with tweening.
|
|
467
491
|
|
|
468
492
|
.key( 2000, { n: 300 })
|
|
469
|
-
.label( 'My first tween!' )
|
|
493
|
+
.label( 'My first tween begins!' )
|
|
470
494
|
.tween( Pacer.sine.in )
|
|
471
495
|
.onKey(( e, p )=> console.log( p.getCurrentKey().label ))
|
|
472
496
|
.onTween(( e )=> console.log( 'Tweened value:', e.n ))
|
|
473
497
|
|
|
474
498
|
.key( 2000, { n: 400 })
|
|
475
|
-
.label( 'My second tween' )
|
|
499
|
+
.label( 'My second tween begins.' )
|
|
476
500
|
.tween( Pacer.quadratic.out )
|
|
477
501
|
.onKey(( e, p )=> console.log( p.getCurrentKey().label ))
|
|
478
502
|
.onTween(( e )=> console.log( 'Tweened value:', e.n ))
|
|
@@ -492,7 +516,7 @@ var p = new Pacer( 'My first Pacer' )
|
|
|
492
516
|
))
|
|
493
517
|
|
|
494
518
|
|
|
495
|
-
// Can haz multiple
|
|
519
|
+
// Can haz multiple tweened values at once?
|
|
496
520
|
// Of course you can!
|
|
497
521
|
|
|
498
522
|
.key( 2000, { n: 600, x: 100 })
|
|
@@ -500,6 +524,27 @@ var p = new Pacer( 'My first Pacer' )
|
|
|
500
524
|
.key( 2000, { n: 700, x: -100 })
|
|
501
525
|
|
|
502
526
|
|
|
527
|
+
// Let’s look at some keyframe declaration variations.
|
|
528
|
+
|
|
529
|
+
.key(
|
|
530
|
+
|
|
531
|
+
2000,
|
|
532
|
+
{ n: 800 },
|
|
533
|
+
( e, p )=> console.log(
|
|
534
|
+
|
|
535
|
+
'💫 Did you know, '+
|
|
536
|
+
'you can actually specify an onKey callback '+
|
|
537
|
+
'right in the keyframe declaration itself?'
|
|
538
|
+
)
|
|
539
|
+
)
|
|
540
|
+
.key( 2000 )
|
|
541
|
+
.values({ n: 900 })
|
|
542
|
+
.onKey(( e, p )=> console.log(
|
|
543
|
+
|
|
544
|
+
'Or keep each argument entirely separate.'
|
|
545
|
+
))
|
|
546
|
+
|
|
547
|
+
|
|
503
548
|
// Totally commenting these out
|
|
504
549
|
// in case you copy and paste this whole thing
|
|
505
550
|
// into your console.
|
|
@@ -516,7 +561,24 @@ var p = new Pacer( 'My first Pacer' )
|
|
|
516
561
|
})
|
|
517
562
|
|
|
518
563
|
|
|
519
|
-
//
|
|
564
|
+
// Pacers are “clamped” by default,
|
|
565
|
+
// ie. their values do not extend to before their first keyframe
|
|
566
|
+
// or extend beyond their final keyframe.
|
|
567
|
+
// Because we’re already clamped, this will do nothing:
|
|
568
|
+
|
|
569
|
+
.clamp()
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
// But what if we wanted to take our keyframes and tweens
|
|
573
|
+
// at either end of the timeline
|
|
574
|
+
// and extend them outward to infinity?
|
|
575
|
+
// We’d better unclamp!
|
|
576
|
+
|
|
577
|
+
.unclamp()
|
|
578
|
+
|
|
579
|
+
|
|
580
|
+
// Now we can have steps beyond our timeline.
|
|
581
|
+
// Note that for our “before” `keyIndex` will be
|
|
520
582
|
// “out of bounds” with a value of -1,
|
|
521
583
|
// so `getCurrentKey()` will return undefined.
|
|
522
584
|
// This is intended. We’re out of keyframes!
|