qarl 1.0.0
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 +21 -0
- package/README.md +12 -0
- package/behaviors/easings.js +72 -0
- package/behaviors/modes.js +47 -0
- package/controllers/FromTo.js +108 -0
- package/core/Core.js +371 -0
- package/core/defaults.js +12 -0
- package/core/events.js +30 -0
- package/emitter/Notifier.js +97 -0
- package/index.js +7 -0
- package/package.json +19 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 qarl
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# QARL (Quantum Animation Remixable Library) π
|
|
2
|
+
|
|
3
|
+
QARL is an animation library for my game engine.
|
|
4
|
+
|
|
5
|
+
New project! π‘ It surely has some bugs, unfinished features, and odd solutions, but I've put a lot of heart and effort into it. Thanks for stopping by β I hope you'll enjoy it! πβ¨
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
Install the library via npm:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install qarl
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
|
|
2
|
+
// created by chatGPT
|
|
3
|
+
const PI2 = Math.PI * 2
|
|
4
|
+
|
|
5
|
+
export const easings = {
|
|
6
|
+
reverse: (t) => 1 - t,
|
|
7
|
+
linear: (t) => t,
|
|
8
|
+
yoyo: (t) => 1 - Math.abs(1 - t * 2),
|
|
9
|
+
|
|
10
|
+
inQuad: (t) => t * t,
|
|
11
|
+
outQuad: (t) => t * (2 - t),
|
|
12
|
+
inOutQuad: (t) => t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t,
|
|
13
|
+
|
|
14
|
+
inCubic: (t) => t * t * t,
|
|
15
|
+
outCubic: (t) => (--t) * t * t + 1,
|
|
16
|
+
inOutCubic: (t) => t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1,
|
|
17
|
+
|
|
18
|
+
inQuart: (t) => t * t * t * t,
|
|
19
|
+
outQuart: (t) => 1 - (--t) * t * t * t,
|
|
20
|
+
inOutQuart: (t) => t < 0.5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t,
|
|
21
|
+
|
|
22
|
+
inQuint: (t) => t * t * t * t * t,
|
|
23
|
+
outQuint: (t) => 1 + (--t) * t * t * t * t,
|
|
24
|
+
inOutQuint: (t) => t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * (--t) * t * t * t * t,
|
|
25
|
+
|
|
26
|
+
inSine: (t) => 1 - Math.cos((t * Math.PI) / 2),
|
|
27
|
+
outSine: (t) => Math.sin((t * Math.PI) / 2),
|
|
28
|
+
inOutSine: (t) => -(Math.cos(Math.PI * t) - 1) / 2,
|
|
29
|
+
|
|
30
|
+
inBack: (t, s = 1.70158) => t * t * ((s + 1) * t - s),
|
|
31
|
+
outBack: (t, s = 1.70158) => ((t -= 1) * t * ((s + 1) * t + s) + 1),
|
|
32
|
+
inOutBack: (t, s = 1.70158) =>
|
|
33
|
+
(t *= 2) < 1
|
|
34
|
+
? 0.5 * (t * t * ((s * 1.525 + 1) * t - s * 1.525))
|
|
35
|
+
: 0.5 * ((t -= 2) * t * ((s * 1.525 + 1) * t + s * 1.525) + 2),
|
|
36
|
+
|
|
37
|
+
inExpo: (t) => (t === 0 ? 0 : Math.pow(2, 10 * (t - 1))),
|
|
38
|
+
outExpo: (t) => (t === 1 ? 1 : 1 - Math.pow(2, -10 * t)),
|
|
39
|
+
inOutExpo: (t) => (
|
|
40
|
+
t === 0
|
|
41
|
+
? 0
|
|
42
|
+
: t === 1
|
|
43
|
+
? 1
|
|
44
|
+
: t < 0.5
|
|
45
|
+
? 0.5 * Math.pow(2, 20 * t - 10)
|
|
46
|
+
: 1 - 0.5 * Math.pow(2, -20 * t + 10)
|
|
47
|
+
),
|
|
48
|
+
|
|
49
|
+
inElastic: (t, a = 1, p = 0.5) => (
|
|
50
|
+
t === 0
|
|
51
|
+
? 0
|
|
52
|
+
: t === 1
|
|
53
|
+
? 1
|
|
54
|
+
: -a * Math.pow(2, 10 * (t - 1)) * Math.sin(((t - 1 - p / PI2 * Math.asin(1 / a)) * PI2) / p)
|
|
55
|
+
),
|
|
56
|
+
outElastic: (t, a = 1, p = 0.5) => (
|
|
57
|
+
t === 0
|
|
58
|
+
? 0
|
|
59
|
+
: t === 1
|
|
60
|
+
? 1
|
|
61
|
+
: a * Math.pow(2, -10 * t) * Math.sin(((t - p / PI2 * Math.asin(1 / a)) * PI2) / p) + 1
|
|
62
|
+
),
|
|
63
|
+
inOutElastic: (t, a = 1, p = 0.5) => (
|
|
64
|
+
t === 0
|
|
65
|
+
? 0
|
|
66
|
+
: t === 1
|
|
67
|
+
? 1
|
|
68
|
+
: t < 0.5
|
|
69
|
+
? -0.5 * a * Math.pow(2, 20 * t - 10) * Math.sin(((20 * t - 11.125) * PI2) / p)
|
|
70
|
+
: 0.5 * a * Math.pow(2, -20 * t + 10) * Math.sin(((20 * t - 11.125) * PI2) / p) + 1
|
|
71
|
+
)
|
|
72
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { easings } from "./easings"
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ΠΠ±ΡΠ΅ΠΊΡ, ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠΈΠΉ ΠΌΠΎΠ΄ΠΈΡΠΈΠΊΠ°ΡΠΎΡΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
5
|
+
* @namespace
|
|
6
|
+
* @property {function} pingPong - Π Π΅Π°Π»ΠΈΠ·ΡΠ΅Ρ ΠΏΠΈΠ½Π³-ΠΏΠΎΠ½Π³ ΡΡΡΠ΅ΠΊΡ Π΄Π»Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
7
|
+
* @property {function} yoyo - Π Π΅Π°Π»ΠΈΠ·ΡΠ΅Ρ ΡΡΡΠ΅ΠΊΡ Π·Π΅ΡΠΊΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΠΎΡΡΠ°ΠΆΠ΅Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
8
|
+
* @property {function} bounce - Π Π΅Π°Π»ΠΈΠ·ΡΠ΅Ρ ΡΡΡΠ΅ΠΊΡ ΠΎΡΡΠΊΠΎΠΊΠ° Π΄Π»Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
9
|
+
* @example
|
|
10
|
+
* const animation = new Core({ time: 1000, mode: modes.pingPong })
|
|
11
|
+
* animation.play()
|
|
12
|
+
* @see {@link Core}
|
|
13
|
+
* @see {@link easings}
|
|
14
|
+
*/
|
|
15
|
+
export const modes = {
|
|
16
|
+
/**
|
|
17
|
+
* Π Π΅Π°Π»ΠΈΠ·ΡΠ΅Ρ ΠΏΠΈΠ½Π³-ΠΏΠΎΠ½Π³ ΡΡΡΠ΅ΠΊΡ Π΄Π»Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
18
|
+
* @private
|
|
19
|
+
* @param {number} t - Π’Π΅ΠΊΡΡΠ΅Π΅ Π²ΡΠ΅ΠΌΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
20
|
+
* @returns {number} ΠΠ·ΠΌΠ΅Π½Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Π΄Π»Ρ ΡΡΡΠ΅ΠΊΡΠ° ΠΏΠΈΠ½Π³-ΠΏΠΎΠ½Π³.
|
|
21
|
+
*/
|
|
22
|
+
pingPong: function (t) {
|
|
23
|
+
return t <= 0.5
|
|
24
|
+
? this._easing(t * 2)
|
|
25
|
+
: 1 - this._easing((t - 0.5) * 2)
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Π Π΅Π°Π»ΠΈΠ·ΡΠ΅Ρ ΡΡΡΠ΅ΠΊΡ Π·Π΅ΡΠΊΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΠΎΡΡΠ°ΠΆΠ΅Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
30
|
+
* @private
|
|
31
|
+
* @param {number} t - Π’Π΅ΠΊΡΡΠ΅Π΅ Π²ΡΠ΅ΠΌΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
32
|
+
* @returns {number} ΠΠ·ΠΌΠ΅Π½Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Π΄Π»Ρ ΡΡΡΠ΅ΠΊΡΠ° Π·Π΅ΡΠΊΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΠΎΡΡΠ°ΠΆΠ΅Π½ΠΈΡ.
|
|
33
|
+
*/
|
|
34
|
+
yoyo: function (t) {
|
|
35
|
+
return this._easing(easings.yoyo(t))
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Π Π΅Π°Π»ΠΈΠ·ΡΠ΅Ρ ΡΡΡΠ΅ΠΊΡ ΠΎΡΡΠΊΠΎΠΊΠ° Π΄Π»Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
40
|
+
* @private
|
|
41
|
+
* @param {number} t - Π’Π΅ΠΊΡΡΠ΅Π΅ Π²ΡΠ΅ΠΌΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
42
|
+
* @returns {number} ΠΠ·ΠΌΠ΅Π½Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π²ΡΠ΅ΠΌΠ΅Π½ΠΈ Π΄Π»Ρ ΡΡΡΠ΅ΠΊΡΠ° ΠΎΡΡΠΊΠΎΠΊΠ°.
|
|
43
|
+
*/
|
|
44
|
+
bounce: function (t) {
|
|
45
|
+
return easings.yoyo(this._easing(t))
|
|
46
|
+
},
|
|
47
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { Core } from "../core/Core"
|
|
2
|
+
|
|
3
|
+
export class FromTo extends Core {
|
|
4
|
+
|
|
5
|
+
static DEFAULTS = {
|
|
6
|
+
...Core.DEFAULTS,
|
|
7
|
+
dynamic: false, // Π² Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΎΠΌ ΡΠΎΡΡΠΎΡΠ½ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΡ from ΠΈ to Π²ΠΎ Π²ΡΠ΅ΠΌΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ
|
|
8
|
+
target: null,
|
|
9
|
+
from: null,
|
|
10
|
+
to: null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
_refreshDynamicProps() {
|
|
14
|
+
super._refreshDynamicProps()
|
|
15
|
+
this._processFromTo()
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
_processFromTo() {
|
|
19
|
+
this.target = this.settings.target
|
|
20
|
+
|
|
21
|
+
this._from = this.settings.from || this._createState(this.settings.to || {}, this.target)
|
|
22
|
+
this._to = this.settings.to || this._createState(this.settings.from || {}, this.target)
|
|
23
|
+
|
|
24
|
+
if (!this.target) {
|
|
25
|
+
this._updateFromTo = Core._noop
|
|
26
|
+
} else if (this.settings.dynamic) {
|
|
27
|
+
this._updateFromTo = this._updateDynamic.bind(this)
|
|
28
|
+
} else {
|
|
29
|
+
this._lerps = []
|
|
30
|
+
this._createLerps(this.target, this._from, this._to)
|
|
31
|
+
this._updateFromTo = this._updateBaked.bind(this)
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
_createState(origPattern = {}, origSource = {}, origTarget = {}) {
|
|
37
|
+
const _copyProperty = (pattern, source, target) => {
|
|
38
|
+
for (const key in pattern) {
|
|
39
|
+
typeof pattern[key] === 'object'
|
|
40
|
+
? target[key] = {} && _copyProperty(pattern[key], source[key], target[key])
|
|
41
|
+
: target[key] = source[key]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
_copyProperty(origPattern, origSource, origTarget)
|
|
46
|
+
return origTarget
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
_createLerpStep(target, objFrom, objTo, propName) {
|
|
50
|
+
const staticDelta = objTo[propName] - objFrom[propName]
|
|
51
|
+
|
|
52
|
+
return (easeValue) => {
|
|
53
|
+
target[propName] = objFrom[propName] + staticDelta * easeValue
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
_createLerps(target, from, to) {
|
|
58
|
+
for (const key in to) {
|
|
59
|
+
typeof to[key] === 'object'
|
|
60
|
+
? this._createLerps(target[key], from[key], to[key])
|
|
61
|
+
: this._lerps.push(this._createLerpStep(target, from, to, key))
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
_update() {
|
|
66
|
+
super._update()
|
|
67
|
+
this._updateFromTo()
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
_updateBaked() {
|
|
71
|
+
this._lerps.forEach(lerpStep => lerpStep(this.easeValue))
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
_updateDynamic(target = this.target, from = this._from, to = this._to) {
|
|
75
|
+
for (const key in to) {
|
|
76
|
+
typeof to[key] === 'object'
|
|
77
|
+
? this._updateDynamic(target[key], from[key], to[key])
|
|
78
|
+
: target[key] = from[key] + (to[key] - from[key]) * this.easeValue
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
from(newFrom = {}) {
|
|
83
|
+
this.tweak({ from: newFrom })
|
|
84
|
+
this._processFromTo()
|
|
85
|
+
return this
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
to(newTo = {}) {
|
|
89
|
+
this.tweak({ to: newTo })
|
|
90
|
+
this._processFromTo()
|
|
91
|
+
return this
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
swap() {
|
|
95
|
+
const temp = this._from
|
|
96
|
+
this._from = this._to
|
|
97
|
+
this._to = temp
|
|
98
|
+
|
|
99
|
+
if (!this.settings.dynamic) {
|
|
100
|
+
this._lerps = []
|
|
101
|
+
this._createLerps(this.target, this._from, this._to)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return this
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
}
|
|
108
|
+
|
package/core/Core.js
ADDED
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
import { Notifier } from "../emitter/Notifier"
|
|
2
|
+
import { DEFAULTS } from "../core/defaults"
|
|
3
|
+
import { EVENTS } from "../core/events"
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Core - ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΠΊΠ»Π°ΡΡ Π΄Π»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΡΠΌΠΈ.
|
|
8
|
+
*
|
|
9
|
+
* @class Core
|
|
10
|
+
* @param {Object} [overrides={}] - ΠΠ±ΡΠ΅ΠΊΡ Π΄Π»Ρ ΠΏΠ΅ΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½ΠΈΡ Π½Π°ΡΡΡΠΎΠ΅ΠΊ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ.
|
|
11
|
+
* @param {Object} [EmitterClass=null] - ΠΠ»Π°ΡΡ Π΄Π»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΡΠΎΠ±ΡΡΠΈΡΠΌΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* const animation = new Core({ time: 1000, easing: easings.inOutQuad });
|
|
15
|
+
* animation.play();
|
|
16
|
+
*
|
|
17
|
+
* @property {Object} DEFAULTS - ΠΠ°ΡΡΡΠΎΠΉΠΊΠΈ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ.
|
|
18
|
+
* @property {number} DEFAULTS.time - ΠΡΠ΅ΠΌΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
19
|
+
* @property {boolean} DEFAULTS.loop - Π€Π»Π°Π³ Π±Π΅ΡΠΊΠΎΠ½Π΅ΡΠ½ΠΎΠ³ΠΎ ΠΏΠΎΠ²ΡΠΎΡΠ΅Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
20
|
+
* @property {function} DEFAULTS.easing - Π€ΡΠ½ΠΊΡΠΈΡ Π΄Π»Ρ ΡΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ ΡΡΡΠ΅ΠΊΡΠΎΠΌ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
21
|
+
* @property {boolean} DEFAULTS.reversed - Π€Π»Π°Π³ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠ³ΠΎ ΠΏΡΠΎΠΈΠ³ΡΡΠ²Π°Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
22
|
+
* @property {number} DEFAULTS.repeat - ΠΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΏΠΎΠ²ΡΠΎΡΠ΅Π½ΠΈΠΉ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
23
|
+
* @property {number} DEFAULTS.delay - ΠΠ°Π΄Π΅ΡΠΆΠΊΠ° ΠΏΠ΅ΡΠ΅Π΄ Π½Π°ΡΠ°Π»ΠΎΠΌ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
24
|
+
*
|
|
25
|
+
* @property {Object} settings - Π’Π΅ΠΊΡΡΠΈΠ΅ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
26
|
+
* @property {number} progress - Π’Π΅ΠΊΡΡΠΈΠΉ ΠΏΡΠΎΠ³ΡΠ΅ΡΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
27
|
+
* @property {boolean} reversed - Π£ΠΊΠ°Π·ΡΠ²Π°Π΅Ρ, ΠΏΡΠΎΠΈΠ³ΡΡΠ²Π°Π΅ΡΡΡ Π»ΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ Π² ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠΌ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠΈ.
|
|
28
|
+
*/
|
|
29
|
+
export class Core {
|
|
30
|
+
static DEFAULTS = DEFAULTS
|
|
31
|
+
|
|
32
|
+
static _noop() { }
|
|
33
|
+
|
|
34
|
+
static mergeConfigs(target, source) {
|
|
35
|
+
for (let key in source) {
|
|
36
|
+
if (typeof source[key] === 'object' && source[key] !== null) {
|
|
37
|
+
if (!target[key] || typeof target[key] !== 'object') {
|
|
38
|
+
target[key] = {}
|
|
39
|
+
}
|
|
40
|
+
Core.mergeConfigs(target[key], source[key])
|
|
41
|
+
} else {
|
|
42
|
+
target[key] = source[key]
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
constructor(overrides = {}, EmitterClass = Notifier) {
|
|
48
|
+
this.settings = {}
|
|
49
|
+
this._emitter = EmitterClass ? new EmitterClass() : null
|
|
50
|
+
this.reset(overrides)
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
55
|
+
* @private
|
|
56
|
+
*/
|
|
57
|
+
_processState() {
|
|
58
|
+
this.step = Core._noop
|
|
59
|
+
this.progress = 0
|
|
60
|
+
this.easeValue = 0
|
|
61
|
+
this.elapsedTime = 0
|
|
62
|
+
this.promise = null
|
|
63
|
+
this._resolve = Core._noop
|
|
64
|
+
this._refreshDynamicProps()
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* ΠΠ±Π½ΠΎΠ²Π»ΡΠ΅Ρ Π΄ΠΈΠ½Π°ΠΌΠΈΡΠ΅ΡΠΊΠΈΠ΅ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
69
|
+
* @private
|
|
70
|
+
*/
|
|
71
|
+
_refreshDynamicProps() {
|
|
72
|
+
this.time = Math.max(this.settings.time, 0)
|
|
73
|
+
this.repeat = this.settings.repeat > 0 ? this.settings.repeat : this.settings.loop ? Infinity : 0
|
|
74
|
+
this.reversed = this.settings.reversed
|
|
75
|
+
this.remainingDelay = this.settings.delay
|
|
76
|
+
|
|
77
|
+
this._emitEvent = this._emitEvent || Core._noop
|
|
78
|
+
this._emitUpdate = this._emitUpdate || Core._noop
|
|
79
|
+
|
|
80
|
+
this._processEasing()
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ ΡΡΠ½ΠΊΡΠΈΡ easing Π΄Π»Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
85
|
+
* @private
|
|
86
|
+
*/
|
|
87
|
+
_processEasing() {
|
|
88
|
+
this._easing = this.reversed ? this._reversedEasing : this.settings.easing
|
|
89
|
+
this._calculateEasing = this.settings.mode ? this.settings.mode.bind(this) : this._easing
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Π Π°ΡΡΡΠΈΡΡΠ²Π°Π΅Ρ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ easing.
|
|
94
|
+
* @param {number} t - ΠΡΠ΅ΠΌΡ ΠΏΡΠΎΠ³ΡΠ΅ΡΡΠ°.
|
|
95
|
+
* @returns {number} - Π Π΅Π·ΡΠ»ΡΡΠ°Ρ ΡΡΠ½ΠΊΡΠΈΠΈ easing Π΄Π»Ρ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠ³ΠΎ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ.
|
|
96
|
+
* @private
|
|
97
|
+
*/
|
|
98
|
+
_reversedEasing(t) {
|
|
99
|
+
return this.settings.easing(1 - t)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* ΠΠ±Π½ΠΎΠ²Π»ΡΠ΅Ρ ΠΏΡΠΎΠ³ΡΠ΅ΡΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ ΠΈ Π²ΡΠ·ΡΠ²Π°Π΅Ρ ΡΠΎΠ±ΡΡΠΈΠ΅ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ.
|
|
104
|
+
* @private
|
|
105
|
+
*/
|
|
106
|
+
_update() {
|
|
107
|
+
this.progress = this.elapsedTime / this.time
|
|
108
|
+
this.easeValue = this._calculateEasing(this.progress)
|
|
109
|
+
this._emitUpdate(EVENTS.UPDATE, { progress: this.progress, ease: this.easeValue })
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* ΠΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Π·Π°Π΄Π΅ΡΠΆΠΊΡ ΠΏΠ΅ΡΠ΅Π΄ Π½Π°ΡΠ°Π»ΠΎΠΌ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
114
|
+
* @param {number} deltaTime - ΠΡΠ΅ΠΌΡ, ΠΏΡΠΎΡΠ΅Π΄ΡΠ΅Π΅ Ρ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅Π³ΠΎ ΡΠ°Π³Π°.
|
|
115
|
+
* @private
|
|
116
|
+
*/
|
|
117
|
+
_stepDelay(deltaTime) {
|
|
118
|
+
this.remainingDelay -= deltaTime
|
|
119
|
+
|
|
120
|
+
if (this.remainingDelay > 0) return
|
|
121
|
+
|
|
122
|
+
this.step = this._stepTime
|
|
123
|
+
this.step(Math.abs(this.remainingDelay))
|
|
124
|
+
|
|
125
|
+
this.remainingDelay = this.settings.delay
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* ΠΠ±ΡΠ°Π±Π°ΡΡΠ²Π°Π΅Ρ Π²ΡΠ΅ΠΌΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
130
|
+
* @param {number} [deltaTime=0] - ΠΡΠ΅ΠΌΡ, ΠΏΡΠΎΡΠ΅Π΄ΡΠ΅Π΅ Ρ ΠΏΡΠ΅Π΄ΡΠ΄ΡΡΠ΅Π³ΠΎ ΡΠ°Π³Π°.
|
|
131
|
+
* @private
|
|
132
|
+
*/
|
|
133
|
+
_stepTime(deltaTime = 0) {
|
|
134
|
+
this.elapsedTime += deltaTime
|
|
135
|
+
|
|
136
|
+
if (this.elapsedTime >= this.time) {
|
|
137
|
+
this.elapsedTime = this.time
|
|
138
|
+
this._update()
|
|
139
|
+
this._complete()
|
|
140
|
+
} else {
|
|
141
|
+
this._update()
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* ΠΡΠ·ΡΠ²Π°Π΅ΡΡΡ ΠΏΡΠΈ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
147
|
+
* @private
|
|
148
|
+
*/
|
|
149
|
+
_complete() {
|
|
150
|
+
if (this.repeat-- > 0) {
|
|
151
|
+
this._repeat()
|
|
152
|
+
} else {
|
|
153
|
+
this._resolve()
|
|
154
|
+
this.stop(false)
|
|
155
|
+
this._emitEvent(EVENTS.COMPLETE)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* ΠΠΎΠ²ΡΠΎΡΡΠ΅Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ, Π΅ΡΠ»ΠΈ ΡΡΡΠ°Π½ΠΎΠ²Π»Π΅Π½Ρ ΠΏΠΎΠ²ΡΠΎΡΠ΅Π½ΠΈΡ.
|
|
161
|
+
* @param {boolean} [withEvent=true] - Π€Π»Π°Π³ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° ΡΠΎΠ±ΡΡΠΈΡ ΠΏΠΎΠ²ΡΠΎΡΠ΅Π½ΠΈΡ.
|
|
162
|
+
* @private
|
|
163
|
+
*/
|
|
164
|
+
_repeat(withEvent = true) {
|
|
165
|
+
this.remainingDelay = this.settings.repeatDelay
|
|
166
|
+
this.elapsedTime = 0
|
|
167
|
+
|
|
168
|
+
if (this.remainingDelay > 0) {
|
|
169
|
+
this.step = this._stepDelay
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
this._update()
|
|
173
|
+
withEvent && this._emitEvent(EVENTS.REPEAT)
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* ΠΠΎΠ³ΠΈΡΡΠ΅Ρ ΠΏΡΠ΅Π΄ΡΠΏΡΠ΅ΠΆΠ΄Π΅Π½ΠΈΠ΅, Π΅ΡΠ»ΠΈ ΡΠΌΠΈΡΡΠ΅Ρ ΡΠΎΠ±ΡΡΠΈΠΉ Π½Π΅ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½.
|
|
178
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
179
|
+
* @private
|
|
180
|
+
*/
|
|
181
|
+
_noEmitter() {
|
|
182
|
+
console.warn('Event emitter is not defined')
|
|
183
|
+
return this
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* ΠΠΎΠ΄ΠΏΠΈΡΡΠ²Π°Π΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ Π½Π° ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠ΅ ΡΠΎΠ±ΡΡΠΈΠ΅.
|
|
188
|
+
* @param {string} event - ΠΠΌΡ ΡΠΎΠ±ΡΡΠΈΡ.
|
|
189
|
+
* @param {function} handler - ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΡΠΎΠ±ΡΡΠΈΡ.
|
|
190
|
+
* @param {boolean} [once=false] - Π€Π»Π°Π³ Π΄Π»Ρ ΠΎΠ΄Π½ΠΎΡΠ°Π·ΠΎΠ²ΠΎΠΉ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠΈ.
|
|
191
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
192
|
+
*/
|
|
193
|
+
on(event, handler, once = false) {
|
|
194
|
+
if (!this._emitter) return this._noEmitter()
|
|
195
|
+
|
|
196
|
+
if (event === EVENTS.UPDATE) {
|
|
197
|
+
this._emitUpdate = this._emitter.emit(event, handler)
|
|
198
|
+
} else {
|
|
199
|
+
this._emit = this._emitter.emit(event, handler)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
once
|
|
203
|
+
? this._emitter.once(event, handler)
|
|
204
|
+
: this._emitter.on(event, handler)
|
|
205
|
+
|
|
206
|
+
return this
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* ΠΠΎΠ΄ΠΏΠΈΡΡΠ²Π°Π΅Ρ ΠΎΠ΄Π½ΠΎΡΠ°Π·ΠΎΠ²ΡΠΉ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ Π½Π° ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠ΅ ΡΠΎΠ±ΡΡΠΈΠ΅.
|
|
211
|
+
* @param {string} event - ΠΠΌΡ ΡΠΎΠ±ΡΡΠΈΡ.
|
|
212
|
+
* @param {function} handler - ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΡΠΎΠ±ΡΡΠΈΡ.
|
|
213
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
214
|
+
*/
|
|
215
|
+
once(event, handler) {
|
|
216
|
+
return this.on(event, handler, true)
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* ΠΡΠΏΠΈΡΡΠ²Π°Π΅Ρ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΠΎΡ ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ ΡΠΎΠ±ΡΡΠΈΡ.
|
|
221
|
+
* @param {string} event - ΠΠΌΡ ΡΠΎΠ±ΡΡΠΈΡ.
|
|
222
|
+
* @param {function} handler - ΠΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΡΠΎΠ±ΡΡΠΈΡ.
|
|
223
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
224
|
+
*/
|
|
225
|
+
off(event, handler) {
|
|
226
|
+
if (!this._emitter) return this._noEmitter()
|
|
227
|
+
|
|
228
|
+
this._emitter.off(event, handler)
|
|
229
|
+
return this
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Π£Π΄Π°Π»ΡΠ΅Ρ Π²ΡΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΈ Π΄Π»Ρ ΡΠΊΠ°Π·Π°Π½Π½ΠΎΠ³ΠΎ ΡΠΎΠ±ΡΡΠΈΡ.
|
|
234
|
+
* @param {string} event - ΠΠΌΡ ΡΠΎΠ±ΡΡΠΈΡ.
|
|
235
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
236
|
+
*/
|
|
237
|
+
removeEvents(event) {
|
|
238
|
+
if (!this._emitter) return this._noEmitter()
|
|
239
|
+
|
|
240
|
+
this._emitEvent = Core._noop
|
|
241
|
+
this._emitUpdate = Core._noop
|
|
242
|
+
|
|
243
|
+
this._emitter.removeAllListeners(event)
|
|
244
|
+
return this
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Π‘Π±ΡΠ°ΡΡΠ²Π°Π΅Ρ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ ΠΊ Π·Π½Π°ΡΠ΅Π½ΠΈΡΠΌ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ.
|
|
249
|
+
* @param {Object} [newSettings=Core.DEFAULTS] - ΠΠΎΠ²ΡΠ΅ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ.
|
|
250
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
251
|
+
*/
|
|
252
|
+
reset(newSettings = this.constructor.DEFAULTS) {
|
|
253
|
+
this.settings = { ...this.constructor.DEFAULTS, ...newSettings }
|
|
254
|
+
this._processState()
|
|
255
|
+
return this
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* ΠΠ·ΠΌΠ΅Π½ΡΠ΅Ρ ΡΠ΅ΠΊΡΡΠΈΠ΅ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
260
|
+
* @param {Object} [newSettings={}] - ΠΠΎΠ²ΡΠ΅ Π½Π°ΡΡΡΠΎΠΉΠΊΠΈ.
|
|
261
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
262
|
+
*/
|
|
263
|
+
tweak(newSettings = {}) {
|
|
264
|
+
Core.mergeConfigs(this.settings, newSettings)
|
|
265
|
+
this._refreshDynamicProps()
|
|
266
|
+
return this
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ Π²ΡΠ΅ΠΌΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
271
|
+
* @param {number} [time=0] - ΠΡΠ΅ΠΌΡ Π΄Π»Ρ ΡΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ.
|
|
272
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
273
|
+
*/
|
|
274
|
+
seek(time = 0, callUpdate = true) {
|
|
275
|
+
this.elapsedTime = Math.min(Math.max(time, 0), this.settings.time)
|
|
276
|
+
callUpdate && this._update()
|
|
277
|
+
return this
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Π£ΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ ΠΏΡΠΎΠ³ΡΠ΅ΡΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
282
|
+
* @param {number} [progress=0] - ΠΡΠΎΠ³ΡΠ΅ΡΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ (ΠΎΡ 0 Π΄ΠΎ 1).
|
|
283
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
284
|
+
*/
|
|
285
|
+
setProgress(progress = 0, callUpdate = true) {
|
|
286
|
+
this.seek(this.settings.time * progress, callUpdate)
|
|
287
|
+
return this
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* ΠΠ΅Π½ΡΠ΅Ρ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΠ΅ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ (ΠΏΡΡΠΌΠΎΠ΅/ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠ΅).
|
|
292
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
293
|
+
*/
|
|
294
|
+
reverse(callUpdate = false) {
|
|
295
|
+
this.reversed = !this.reversed
|
|
296
|
+
this.seek(this.settings.time - this.elapsedTime, callUpdate)
|
|
297
|
+
this._processEasing()
|
|
298
|
+
|
|
299
|
+
return this
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* ΠΠ°ΠΏΡΡΠΊΠ°Π΅Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ.
|
|
304
|
+
* @param {boolean} [withEvent=true] - Π€Π»Π°Π³ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° ΡΠΎΠ±ΡΡΠΈΡ ΠΏΡΠΈ Π·Π°ΠΏΡΡΠΊΠ΅.
|
|
305
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
306
|
+
*/
|
|
307
|
+
play(withEvent = true) {
|
|
308
|
+
if (this.isPlaying) return this
|
|
309
|
+
|
|
310
|
+
withEvent && this._emitEvent(EVENTS.PLAY)
|
|
311
|
+
if (this.remainingDelay > 0) {
|
|
312
|
+
this.step = this._stepDelay
|
|
313
|
+
} else {
|
|
314
|
+
this.step = this._stepTime
|
|
315
|
+
this._emitEvent(EVENTS.BEGIN)
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return this
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* ΠΠ°ΠΏΡΡΠΊΠ°Π΅Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ Ρ Π²ΠΎΠ·Π²ΡΠ°ΡΠ΅Π½ΠΈΠ΅ΠΌ Promise.
|
|
323
|
+
* @param {Promise} [promise=this.promise] - ΠΠ±ΡΠ΅ΠΊΡ Promise Π΄Π»Ρ ΡΠ°Π·ΡΠ΅ΡΠ΅Π½ΠΈΡ ΠΏΠΎ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ.
|
|
324
|
+
* @returns {Promise} - Promise, ΠΊΠΎΡΠΎΡΡΠΉ ΡΠ°Π·ΡΠ΅ΡΠΈΡΡΡ ΠΏΡΠΈ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
325
|
+
*/
|
|
326
|
+
playPromise(promise = this.promise) {
|
|
327
|
+
this.play()
|
|
328
|
+
this.promise = promise || new Promise(resolve => this._resolve = resolve)
|
|
329
|
+
return this.promise
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* ΠΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ.
|
|
334
|
+
* @param {boolean} [withEvent=true] - Π€Π»Π°Π³ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° ΡΠΎΠ±ΡΡΠΈΡ ΠΏΡΠΈ ΠΎΡΡΠ°Π½ΠΎΠ²ΠΊΠ΅.
|
|
335
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
336
|
+
*/
|
|
337
|
+
stop(withEvent = true) {
|
|
338
|
+
this._processState()
|
|
339
|
+
withEvent && this._emitEvent(EVENTS.STOP)
|
|
340
|
+
return this
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* ΠΡΠΈΠΎΡΡΠ°Π½Π°Π²Π»ΠΈΠ²Π°Π΅Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ.
|
|
345
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
346
|
+
*/
|
|
347
|
+
pause() {
|
|
348
|
+
this.step = Core._noop
|
|
349
|
+
this._emitEvent(EVENTS.PAUSE)
|
|
350
|
+
return this
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* ΠΠΎΠ²ΡΠΎΡΠ½ΠΎ Π·Π°ΠΏΡΡΠΊΠ°Π΅Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ Ρ Π½Π°ΡΠ°Π»ΡΠ½ΠΎΠ³ΠΎ ΡΠΎΡΡΠΎΡΠ½ΠΈΡ.
|
|
355
|
+
* @param {boolean} [withEvent=true] - Π€Π»Π°Π³ Π΄Π»Ρ Π²ΡΠ·ΠΎΠ²Π° ΡΠΎΠ±ΡΡΠΈΡ ΠΏΡΠΈ ΠΏΠ΅ΡΠ΅Π·Π°ΠΏΡΡΠΊΠ΅.
|
|
356
|
+
* @returns {Core} Π’Π΅ΠΊΡΡΠΈΠΉ ΡΠΊΠ·Π΅ΠΌΠΏΠ»ΡΡ Π΄Π»Ρ ΡΠ΅ΠΏΠΎΡΠ΅ΠΊ Π²ΡΠ·ΠΎΠ²ΠΎΠ².
|
|
357
|
+
*/
|
|
358
|
+
replay(withEvent = true) {
|
|
359
|
+
this.stop(withEvent)
|
|
360
|
+
this.play(withEvent)
|
|
361
|
+
return this
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* ΠΠΎΠ·Π²ΡΠ°ΡΠ°Π΅Ρ, Π°ΠΊΡΠΈΠ²Π½Π° Π»ΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ.
|
|
366
|
+
* @returns {boolean} - true, Π΅ΡΠ»ΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΡ Π²ΠΎΡΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΡΡ, ΠΈΠ½Π°ΡΠ΅ false.
|
|
367
|
+
*/
|
|
368
|
+
get isPlaying() {
|
|
369
|
+
return this.step !== Core._noop
|
|
370
|
+
}
|
|
371
|
+
}
|
package/core/defaults.js
ADDED
package/core/events.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ΠΠ±ΡΠ΅ΠΊΡ, ΡΠΎΠ΄Π΅ΡΠΆΠ°ΡΠΈΠΉ ΡΠΎΠ±ΡΡΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
3
|
+
* @namespace
|
|
4
|
+
* @property {string} PLAY - Π‘ΠΎΠ±ΡΡΠΈΠ΅ Π½Π°ΡΠ°Π»Π° Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
5
|
+
* @property {string} STOP - Π‘ΠΎΠ±ΡΡΠΈΠ΅ ΠΎΡΡΠ°Π½ΠΎΠ²ΠΊΠΈ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
6
|
+
* @property {string} BEGIN - Π‘ΠΎΠ±ΡΡΠΈΠ΅ ΠΏΠ°ΡΠ·Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
7
|
+
* @property {string} PAUSE - Π‘ΠΎΠ±ΡΡΠΈΠ΅ ΠΏΠ°ΡΠ·Ρ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
8
|
+
* @property {string} UPDATE - Π‘ΠΎΠ±ΡΡΠΈΠ΅ ΠΎΠ±Π½ΠΎΠ²Π»Π΅Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
9
|
+
* @property {string} REPEAT - Π‘ΠΎΠ±ΡΡΠΈΠ΅ ΠΏΠΎΠ²ΡΠΎΡΠ΅Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
10
|
+
* @property {string} REVERSE - Π‘ΠΎΠ±ΡΡΠΈΠ΅ ΠΏΠΎΠ²ΡΠΎΡΠ΅Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
11
|
+
* @property {string} COMPLETE - Π‘ΠΎΠ±ΡΡΠΈΠ΅ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
12
|
+
* @property {string} INTERRUPT - Π‘ΠΎΠ±ΡΡΠΈΠ΅ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ Π°Π½ΠΈΠΌΠ°ΡΠΈΠΈ.
|
|
13
|
+
* @example
|
|
14
|
+
*
|
|
15
|
+
* animation.on(EVENTS.complete, () => console.log('ΠΠ½ΠΈΠΌΠ°ΡΠΈΡ Π·Π°Π²Π΅ΡΡΠ΅Π½Π°'))
|
|
16
|
+
* animation.once(EVENTS.complete, () => console.log('ΠΠ½ΠΈΠΌΠ°ΡΠΈΡ Π·Π°Π²Π΅ΡΡΠ΅Π½Π°'))
|
|
17
|
+
*
|
|
18
|
+
* @see {@link Core}
|
|
19
|
+
*/
|
|
20
|
+
export const EVENTS = {
|
|
21
|
+
PLAY: 'play',
|
|
22
|
+
STOP: 'stop',
|
|
23
|
+
BEGIN: 'begin',
|
|
24
|
+
PAUSE: 'pause',
|
|
25
|
+
UPDATE: 'update',
|
|
26
|
+
REPEAT: 'repeat',
|
|
27
|
+
REVERSE: 'reverse',
|
|
28
|
+
COMPLETE: 'complete',
|
|
29
|
+
INTERRUPT: 'interrupt',
|
|
30
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
export class Notifier {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.events = {}
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* ΠΠΎΠ΄ΠΏΠΈΡΠΊΠ° Π½Π° ΡΠΎΠ±ΡΡΠΈΠ΅
|
|
8
|
+
* @param {string} eventName - ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ
|
|
9
|
+
* @param {function} listener - Π€ΡΠ½ΠΊΡΠΈΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΡΠΎΠ±ΡΡΠΈΡ
|
|
10
|
+
*/
|
|
11
|
+
on(eventName, listener) {
|
|
12
|
+
if (!this.events[eventName]) {
|
|
13
|
+
this.events[eventName] = []
|
|
14
|
+
}
|
|
15
|
+
this.events[eventName].push(listener)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* ΠΡΠΏΠΈΡΠΊΠ° ΠΎΡ ΡΠΎΠ±ΡΡΠΈΡ
|
|
20
|
+
* @param {string} eventName - ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ
|
|
21
|
+
* @param {function} listener - Π€ΡΠ½ΠΊΡΠΈΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΡΠΎΠ±ΡΡΠΈΡ
|
|
22
|
+
*/
|
|
23
|
+
off(eventName, listener) {
|
|
24
|
+
if (!this.events[eventName]) return
|
|
25
|
+
this.events[eventName] = this.events[eventName].filter(l => l !== listener)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* ΠΠ΅Π½Π΅ΡΠ°ΡΠΈΡ ΡΠΎΠ±ΡΡΠΈΡ
|
|
30
|
+
* @param {string} eventName - ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ
|
|
31
|
+
* @param {...any} args - ΠΡΠ³ΡΠΌΠ΅Π½ΡΡ, ΠΏΠ΅ΡΠ΅Π΄Π°Π²Π°Π΅ΠΌΡΠ΅ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΡ ΡΠΎΠ±ΡΡΠΈΡ
|
|
32
|
+
*/
|
|
33
|
+
emit(eventName, ...args) {
|
|
34
|
+
if (!this.events[eventName]) return
|
|
35
|
+
this.events[eventName].forEach(listener => listener(...args))
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Π Π°Π·ΠΎΠ²Π°Ρ ΠΏΠΎΠ΄ΠΏΠΈΡΠΊΠ° Π½Π° ΡΠΎΠ±ΡΡΠΈΠ΅
|
|
40
|
+
* @param {string} eventName - ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ
|
|
41
|
+
* @param {function} listener - Π€ΡΠ½ΠΊΡΠΈΡ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊ ΡΠΎΠ±ΡΡΠΈΡ
|
|
42
|
+
*/
|
|
43
|
+
once(eventName, listener) {
|
|
44
|
+
const onceListener = (...args) => {
|
|
45
|
+
this.off(eventName, onceListener)
|
|
46
|
+
listener(...args)
|
|
47
|
+
}
|
|
48
|
+
this.on(eventName, onceListener)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* ΠΠΎΠ»ΡΡΠΈΡΡ ΡΠΏΠΈΡΠΎΠΊ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ² ΡΠΎΠ±ΡΡΠΈΡ
|
|
53
|
+
* @param {string} eventName - ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ
|
|
54
|
+
* @returns {function[]} Π‘ΠΏΠΈΡΠΎΠΊ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ²
|
|
55
|
+
*/
|
|
56
|
+
getListeners(eventName) {
|
|
57
|
+
return this.events[eventName] || []
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* ΠΠΎΠ»ΡΡΠΈΡΡ ΠΊΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ² ΡΠΎΠ±ΡΡΠΈΡ
|
|
62
|
+
* @param {string} eventName - ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ
|
|
63
|
+
* @returns {number} ΠΠΎΠ»ΠΈΡΠ΅ΡΡΠ²ΠΎ ΠΎΠ±ΡΠ°Π±ΠΎΡΡΠΈΠΊΠΎΠ²
|
|
64
|
+
*/
|
|
65
|
+
getListenerCount(eventName) {
|
|
66
|
+
return this.events[eventName] ? this.events[eventName].length : 0
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Π£Π΄Π°Π»Π΅Π½ΠΈΠ΅ Π²ΡΠ΅Ρ
ΠΏΠΎΠ΄ΠΏΠΈΡΠΎΠΊ ΠΈΠ»ΠΈ ΠΏΠΎΠ΄ΠΏΠΈΡΠΎΠΊ ΠΎΠΏΡΠ΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ³ΠΎ ΡΠΈΠΏΠ°
|
|
71
|
+
* @param {string} [eventName] - ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ (ΠΎΠΏΡΠΈΠΎΠ½Π°Π»ΡΠ½ΠΎ)
|
|
72
|
+
*/
|
|
73
|
+
removeAllListeners(eventName) {
|
|
74
|
+
if (eventName) {
|
|
75
|
+
delete this.events[eventName]
|
|
76
|
+
} else {
|
|
77
|
+
this.events = {}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* ΠΠΎΠ»ΡΡΠΈΡΡ ΡΠΏΠΈΡΠΎΠΊ Π²ΡΠ΅Ρ
ΡΠΎΠ±ΡΡΠΈΠΉ
|
|
83
|
+
* @returns {string[]} Π‘ΠΏΠΈΡΠΎΠΊ Π½Π°Π·Π²Π°Π½ΠΈΠΉ ΡΠΎΠ±ΡΡΠΈΠΉ
|
|
84
|
+
*/
|
|
85
|
+
getEventNames() {
|
|
86
|
+
return Object.keys(this.events)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* ΠΡΠΎΠ²Π΅ΡΠΈΡΡ Π½Π°Π»ΠΈΡΠΈΠ΅ ΠΏΠΎΠ΄ΠΏΠΈΡΡΠΈΠΊΠΎΠ² Π½Π° ΡΠΎΠ±ΡΡΠΈΠ΅
|
|
91
|
+
* @param {string} eventName - ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΡΠΎΠ±ΡΡΠΈΡ
|
|
92
|
+
* @returns {boolean} True, Π΅ΡΠ»ΠΈ Π΅ΡΡΡ ΠΏΠΎΠ΄ΠΏΠΈΡΡΠΈΠΊΠΈ, ΠΈΠ½Π°ΡΠ΅ False
|
|
93
|
+
*/
|
|
94
|
+
hasListeners(eventName) {
|
|
95
|
+
return this.getListenerCount(eventName) > 0
|
|
96
|
+
}
|
|
97
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { Core } from './core/Core'
|
|
2
|
+
export { EVENTS } from './core/events'
|
|
3
|
+
export { DEFAULTS } from './core/defaults'
|
|
4
|
+
export { Notifier } from './emitter/Notifier'
|
|
5
|
+
export { FromTo } from './controllers/FromTo'
|
|
6
|
+
export { easings } from './behaviors/easings'
|
|
7
|
+
export { modes } from './behaviors/modes'
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "qarl",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "simple animation library",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
8
|
+
},
|
|
9
|
+
"repository": {
|
|
10
|
+
"type": "git",
|
|
11
|
+
"url": "git+https://github.com/ThreePixDroid/qarl.git"
|
|
12
|
+
},
|
|
13
|
+
"author": "threepixdroid",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/ThreePixDroid/qarl/issues"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/ThreePixDroid/qarl#readme"
|
|
19
|
+
}
|