@litecanvas/utils 0.14.0 → 0.16.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.
@@ -0,0 +1,170 @@
1
+ import "litecanvas"
2
+
3
+ const HALF_PI = Math.PI / 2
4
+
5
+ export const tween = (object, prop, toValue, duration = 1, easing = LINEAR) => {
6
+ return new TweenController(object, prop, toValue, duration, easing)
7
+ }
8
+
9
+ export const LINEAR = (n) => n
10
+
11
+ export const EASE_IN = (n) => n * n
12
+ export const EASE_OUT = (n) => -n * (n - 2.0)
13
+ export const EASE_IN_OUT = (n) => {
14
+ if (n < 0.5) {
15
+ return 2.0 * n * n
16
+ }
17
+ return -2.0 * n * n + 4.0 * n - 1.0
18
+ }
19
+
20
+ export const BACK_IN = (n) => n * n * n - n * Math.sin(n * Math.PI)
21
+ export const BACK_OUT = (n) => {
22
+ let a = 1.0 - n
23
+ return 1.0 - (a * a * a - a * Math.sin(a * Math.PI))
24
+ }
25
+ export const BACK_IN_OUT = (n) => {
26
+ if (n < 0.5) {
27
+ let a = 2.0 * n
28
+ return 0.5 * (a * a * a - a * Math.sin(a * Math.PI))
29
+ }
30
+ let a = 1.0 - (2.0 * n - 1.0)
31
+ return 0.5 * (1.0 - (a * a * a - a * Math.sin(n * Math.PI))) + 0.5
32
+ }
33
+
34
+ export const ELASTIC_IN = (n) => {
35
+ return Math.sin(13 * HALF_PI * n) * Math.pow(2, 10 * (n - 1))
36
+ }
37
+ export const ELASTIC_OUT = (n) => {
38
+ return Math.sin(-13 * HALF_PI * (n + 1)) * Math.pow(2, -10 * n) + 1
39
+ }
40
+ export const ELASTIC_IN_OUT = (n) => {
41
+ if (n < 0.5) {
42
+ let a = Math.sin(13 * HALF_PI * (2 * n))
43
+ let b = Math.pow(2, 10 * (2 * n - 1))
44
+ return 0.5 * a * b
45
+ }
46
+ let a = Math.sin(-13 * HALF_PI * (2 * n - 1 + 1))
47
+ let b = Math.pow(2, -10 * (2 * n - 1))
48
+ return 0.5 * (a * b + 2)
49
+ }
50
+
51
+ export const BOUNCE_IN = (n) => 1 - BOUNCE_OUT(1 - n)
52
+ export const BOUNCE_OUT = (n) => {
53
+ if (n < 4.0 / 11.0) {
54
+ return (121.0 * n * n) / 16.0
55
+ } else if (n < 8.0 / 11.0) {
56
+ return (363.0 / 40.0) * n * n - (99.0 / 10.0) * n + 17.0 / 5.0
57
+ } else if (n < 9.0 / 10.0) {
58
+ return (4356.0 / 361.0) * n * n - (35442.0 / 1805.0) * n + 16061.0 / 1805.0
59
+ }
60
+ return (54.0 / 5.0) * n * n - (513.0 / 25.0) * n + 268.0 / 25.0
61
+ }
62
+ export const BOUNCE_IN_OUT = (n) => {
63
+ if (n < 0.5) {
64
+ return 0.5 * BOUNCE_IN(n * 2)
65
+ }
66
+ return 0.5 * BOUNCE_OUT(n * 2 - 1) + 0.5
67
+ }
68
+
69
+ class TweenController {
70
+ /** @type {boolean} */
71
+ running = false
72
+
73
+ /** @type {*} */
74
+ _o
75
+ /** @type {string} */
76
+ _p
77
+ /** @type {number} */
78
+ _x
79
+ /** @type {number} */
80
+ _d
81
+ /** @type {(x: number) => number} */
82
+ _e
83
+ /** @type {Function[]} */
84
+ _cb = []
85
+ /** @type {number} */
86
+ _t = 0
87
+ /** @type {Function} */
88
+ _u = 0
89
+ /** @type {LitecanvasInstance} */
90
+ _lc
91
+
92
+ /**
93
+ * @param {*} object
94
+ * @param {string} prop
95
+ * @param {number} toValue
96
+ * @param {number} duration
97
+ * @param {(x: number) => number} easing
98
+ */
99
+ constructor(object, prop, toValue, duration, easing) {
100
+ this._o = object
101
+ this._p = prop
102
+ this._x = toValue
103
+ this._d = duration
104
+ this._e = easing
105
+ }
106
+
107
+ /**
108
+ *
109
+ * @param {LitecanvasInstance} engine
110
+ */
111
+ start(engine = globalThis) {
112
+ if (!this.running) {
113
+ this.stop()
114
+ }
115
+
116
+ const fromValue = this._o[this._p] || 0
117
+
118
+ this._lc = engine
119
+ this._u = engine.listen("update", (dt) => {
120
+ this._o[this._p] = engine.lerp(
121
+ fromValue,
122
+ this._x,
123
+ this._e(this._t / this._d)
124
+ )
125
+ this._t += dt
126
+ if (this._t >= this._d) {
127
+ this._o[this._p] = this._x
128
+ this.stop()
129
+ }
130
+ })
131
+
132
+ this.running = true
133
+
134
+ return this
135
+ }
136
+
137
+ /**
138
+ * @param {Function} callback
139
+ */
140
+ onEnd(callback) {
141
+ this._cb.push(callback)
142
+ }
143
+
144
+ /**
145
+ * @param {boolean} completed if `false` don't call the `onEnd()` registered callbacks.
146
+ * @returns
147
+ */
148
+ stop(completed = true) {
149
+ if (!this.running || !this._u) return
150
+
151
+ this.running = false
152
+
153
+ this._u()
154
+
155
+ if (completed) {
156
+ for (const callback of this._cb) {
157
+ callback(this._o)
158
+ }
159
+ }
160
+ }
161
+
162
+ reset() {
163
+ this._cb.length = 0
164
+ this.stop()
165
+ }
166
+
167
+ get progress() {
168
+ return this.running ? this._t / this._d : 0
169
+ }
170
+ }
@@ -150,8 +150,9 @@ export const vecDiv = (v, x, y = x) => {
150
150
  return vecDiv(v, x.x, x.y)
151
151
  }
152
152
 
153
- v.x /= x
154
- v.y /= y
153
+ // prevent division by zero
154
+ v.x /= x || 1
155
+ v.y /= y || 1
155
156
 
156
157
  return v
157
158
  }