@ax-design/reveal-highlight 0.4.2 → 0.5.3

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.
Files changed (74) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +75 -75
  3. package/build/BaseConfig.d.ts +5 -1
  4. package/build/BaseConfig.d.ts.map +1 -1
  5. package/build/CanvasConfig.d.ts +7 -1
  6. package/build/CanvasConfig.d.ts.map +1 -1
  7. package/build/ComputedStyleStorage.d.ts.map +1 -1
  8. package/build/CustomElements.d.ts +20 -4
  9. package/build/CustomElements.d.ts.map +1 -1
  10. package/build/RevealBoundryStore.d.ts +4 -0
  11. package/build/RevealBoundryStore.d.ts.map +1 -1
  12. package/build/RevealStateManager.d.ts +5 -1
  13. package/build/RevealStateManager.d.ts.map +1 -1
  14. package/build/main.js +113 -82
  15. package/build/utils/types.d.ts +2 -10
  16. package/build/utils/types.d.ts.map +1 -1
  17. package/es/BaseConfig.d.ts +46 -42
  18. package/es/BaseConfig.d.ts.map +1 -1
  19. package/es/BaseConfig.js +241 -219
  20. package/es/BaseConfig.js.map +1 -1
  21. package/es/CanvasConfig.d.ts +21 -15
  22. package/es/CanvasConfig.d.ts.map +1 -1
  23. package/es/CanvasConfig.js +332 -320
  24. package/es/CanvasConfig.js.map +1 -1
  25. package/es/ComputedStyleStorage.d.ts +8 -8
  26. package/es/ComputedStyleStorage.d.ts.map +1 -1
  27. package/es/ComputedStyleStorage.js +68 -58
  28. package/es/ComputedStyleStorage.js.map +1 -1
  29. package/es/CustomElements.d.ts +75 -59
  30. package/es/CustomElements.d.ts.map +1 -1
  31. package/es/CustomElements.js +296 -233
  32. package/es/CustomElements.js.map +1 -1
  33. package/es/Profiler.d.ts +12 -12
  34. package/es/Profiler.js +31 -31
  35. package/es/RevealBoundryStore.d.ts +80 -76
  36. package/es/RevealBoundryStore.d.ts.map +1 -1
  37. package/es/RevealBoundryStore.js +269 -248
  38. package/es/RevealBoundryStore.js.map +1 -1
  39. package/es/RevealStateManager.d.ts +19 -15
  40. package/es/RevealStateManager.d.ts.map +1 -1
  41. package/es/RevealStateManager.js +99 -73
  42. package/es/RevealStateManager.js.map +1 -1
  43. package/es/SvgConfig.d.ts +16 -16
  44. package/es/SvgConfig.js +345 -345
  45. package/es/config.d.ts +4 -4
  46. package/es/config.js +21 -21
  47. package/es/index.d.ts +5 -5
  48. package/es/index.js +205 -205
  49. package/es/tsconfig.tsbuildinfo +1 -1
  50. package/es/utils/extractRGBValue.d.ts +1 -1
  51. package/es/utils/extractRGBValue.js +47 -47
  52. package/es/utils/isValidateBorderDecorationType.d.ts +2 -2
  53. package/es/utils/isValidateBorderDecorationType.js +9 -9
  54. package/es/utils/types.d.ts +94 -102
  55. package/es/utils/types.d.ts.map +1 -1
  56. package/es/utils/types.js +1 -1
  57. package/es/variables.d.ts +1 -1
  58. package/es/variables.js +1 -1
  59. package/package.json +35 -34
  60. package/src/BaseConfig.ts +332 -310
  61. package/src/CanvasConfig.ts +420 -415
  62. package/src/ComputedStyleStorage.ts +102 -89
  63. package/src/CustomElements.ts +344 -272
  64. package/src/Profiler.ts +44 -44
  65. package/src/RevealBoundryStore.ts +315 -291
  66. package/src/RevealStateManager.ts +109 -86
  67. package/src/SvgConfig.ts +422 -422
  68. package/src/config.ts +26 -26
  69. package/src/cssTypedOM.d.ts +52 -52
  70. package/src/index.ts +219 -219
  71. package/src/utils/extractRGBValue.ts +58 -58
  72. package/src/utils/isValidateBorderDecorationType.ts +8 -8
  73. package/src/utils/types.ts +97 -105
  74. package/src/variables.ts +1 -1
@@ -1,291 +1,315 @@
1
- import { CanvasConfig } from './CanvasConfig.js';
2
- import { SvgConfig } from './SvgConfig.js';
3
-
4
- type Config = CanvasConfig | SvgConfig;
5
-
6
- export class RevealBoundaryStore {
7
- id: number;
8
- container: HTMLElement;
9
-
10
- // The current cursor position relative to window.
11
- clientX = -1000;
12
- clientY = -1000;
13
-
14
- // The cursor position of painted reveal effect.
15
- paintedClientX = -1000;
16
- paintedClientY = -1000;
17
-
18
- mouseInBoundary = false;
19
- canvasList: Config[] = [];
20
-
21
- animationQueue: Config[] = [];
22
- animationFrame: number | null = null;
23
-
24
- mouseUpClientX = null;
25
- mouseUpClientY = null;
26
- mouseDownAnimateStartFrame = null;
27
- mouseDownAnimateCurrentFrame = null;
28
- mouseDownAnimateReleasedFrame = null;
29
- mouseDownAnimateLogicFrame = null;
30
- mousePressed = false;
31
- mouseReleased = false;
32
-
33
- maxRadius = -1;
34
-
35
- requestedAnimationFrame = false;
36
-
37
- constructor(id: number, $el: HTMLElement) {
38
- this.id = id;
39
- this.container = $el;
40
- }
41
-
42
- addReveal = ($element: HTMLCanvasElement | SVGElement, $container: HTMLElement) => {
43
- let config: Config;
44
- const elementType = Object.prototype.toString.call($element);
45
-
46
- if (elementType === '[object HTMLCanvasElement]') {
47
- config = new CanvasConfig(this, $element as HTMLCanvasElement, $container);
48
- } else if (elementType === '[object SVGSVGElement]') {
49
- config = new SvgConfig(this, $element as SVGSVGElement, $container);
50
- } else {
51
- throw new TypeError(`Unknown element type, got: ${elementType}, Canvas or SVG element expected.`)
52
- }
53
-
54
- config.cacheBoundingRect();
55
- config.cacheCanvasPaintingStyle();
56
- config.updateCachedBitmap();
57
-
58
- this.canvasList.push(config);
59
- };
60
-
61
- removeReveal = ($el: HTMLCanvasElement | SVGElement) => {
62
- this.canvasList = this.canvasList.filter((config) => {
63
- return config && config.element !== $el;
64
- });
65
- };
66
-
67
- updateMaxRadius = (x: number) => {
68
- this.maxRadius = Math.max(x, this.maxRadius);
69
- };
70
-
71
- requestPaintAll = (cleanup?: boolean) => {
72
- if (this.requestedAnimationFrame) return;
73
- this.requestedAnimationFrame = true;
74
-
75
- this.animationFrame = window.requestAnimationFrame((frame) => {
76
- this.requestedAnimationFrame = false;
77
- this.paintAll(cleanup ? -1 : frame, true);
78
- });
79
- };
80
-
81
- updatePointerPosition = (x: number, y: number) => {
82
- this.clientX = x;
83
- this.clientY = y;
84
-
85
- const boundingBox = this.container.getBoundingClientRect();
86
-
87
- let mouseInBoundary = true;
88
-
89
- if (x < boundingBox.left - this.maxRadius) mouseInBoundary = false;
90
- if (x > boundingBox.right + this.maxRadius) mouseInBoundary = false;
91
- if (y < boundingBox.top - this.maxRadius) mouseInBoundary = false;
92
- if (y > boundingBox.bottom + this.maxRadius) mouseInBoundary = false;
93
-
94
- this.mouseInBoundary = mouseInBoundary;
95
- }
96
-
97
- onPointerMoveOnScreen = (x: number, y: number) => {
98
- this.updatePointerPosition(x, y);
99
- if (!this.mouseInBoundary) return;
100
- this.requestPaintAll();
101
- return true;
102
- };
103
-
104
- /**
105
- * Repaint all canvas while user's pointer has entered the boundary.
106
- */
107
- onPointerEnterBoundary = () => {
108
- this.mouseInBoundary = true;
109
-
110
- if (!this.animationFrame) {
111
- this.requestPaintAll();
112
- }
113
- };
114
-
115
- /**
116
- * Clear all canvas while user's pointer leave the bounary.
117
- */
118
- onPointerLeaveBoundary = () => {
119
- this.mouseInBoundary = false;
120
- this.requestPaintAll(true);
121
- };
122
-
123
- /**
124
- * The painting method that draw everything on your screen.
125
- * @param frame current frame index, if this value is 0, it means all canvas
126
- * should be cleaned.
127
- * @param skipSamePointerPositionCheck Literally.
128
- */
129
- private paintAll = (frame: number, skipSamePointerPositionCheck?: boolean) => {
130
- if (!skipSamePointerPositionCheck && !this.mouseInBoundary && this.animationQueue.length === 0) {
131
- return;
132
- }
133
-
134
- // Animation duration checkup
135
- for (let i = 0; i < this.animationQueue.length; i++) {
136
- const config = this.animationQueue[i];
137
-
138
- if (!frame || config.currentFrameId === frame) {
139
- continue;
140
- }
141
-
142
- config.currentFrameId = frame;
143
-
144
- // Initialize the animation parameter
145
- if (config.mouseDownAnimateStartFrame === null) {
146
- config.mouseDownAnimateStartFrame = frame;
147
- }
148
-
149
- // Calculate how long the animation has been playing
150
- const relativeFrame = frame - config.mouseDownAnimateStartFrame;
151
- config.mouseDownAnimateCurrentFrame = relativeFrame;
152
-
153
- const speed = config.cachedStyle.pressAnimationSpeed;
154
- const accelerateRate = config.cachedStyle.releaseAnimationAccelerateRate;
155
-
156
- // We assume that Ripple is a one-way linear process from
157
- // no diffusion to fully diffused,
158
- // and Logic Frame represents the progress of the animation
159
- // in this process.
160
- let unitLogicFrame = relativeFrame;
161
- if (config.mouseReleased && config.mouseDownAnimateReleasedFrame) {
162
- unitLogicFrame += (relativeFrame - config.mouseDownAnimateReleasedFrame) * accelerateRate;
163
- }
164
- config.mouseDownAnimateLogicFrame = unitLogicFrame / speed;
165
-
166
- if (config.mouseDownAnimateLogicFrame > 1) {
167
- // It will be cleaned later
168
- config.cleanedUpForAnimation = true;
169
- }
170
- }
171
-
172
- // Paint the canvas one by one
173
- for (let i = 0; i < this.canvasList.length; i++) {
174
- const config = this.canvasList[i];
175
- config.currentFrameId = frame;
176
-
177
- if (config.cleanedUpForAnimation) {
178
- this.cleanUpAnimationUnit(config, false);
179
- config.cleanedUpForAnimation = false;
180
- } else {
181
- const isPlayingAnimation = this.animationQueue.indexOf(config) === -1;
182
-
183
- if (this.mouseInBoundary || isPlayingAnimation) {
184
- config.paint(skipSamePointerPositionCheck);
185
- } else {
186
- config.clear(false);
187
- }
188
- }
189
- }
190
-
191
- this.paintedClientX = this.clientX;
192
- this.paintedClientY = this.clientY;
193
-
194
- if (this.mouseInBoundary || this.animationQueue.length !== 0) {
195
- this.requestPaintAll();
196
- } else {
197
- this.animationFrame = null;
198
- }
199
- };
200
-
201
- /**
202
- * Clear all canvas.
203
- */
204
- clearAll = (forAnimation: boolean) => {
205
- this.cleanupAnimation(forAnimation, true);
206
- };
207
-
208
- /**
209
- * This is the effect while user pressed on the reveal highlight,
210
- * the ripple start to spread slowly.
211
- */
212
- initializeAnimation = () => {
213
- const config = this.canvasList.find((x) => x.mouseInCanvas());
214
-
215
- if (!config) return;
216
-
217
- if (!this.animationQueue.includes(config)) {
218
- this.animationQueue.push(config);
219
- }
220
-
221
- config.mouseDownAnimateStartFrame = null;
222
- config.mousePressed = true;
223
- config.mouseReleased = false;
224
- };
225
-
226
- /**
227
- * This is the effect while user released it's pointer, the spreading
228
- * ripple animation will start to accelerate.
229
- */
230
- switchAnimation = () => {
231
- for (let i = 0; i < this.animationQueue.length; i++) {
232
- const config = this.animationQueue[i];
233
-
234
- if (!config.mouseReleased) {
235
- config.mouseReleased = true;
236
- config.mouseDownAnimateReleasedFrame = config.mouseDownAnimateCurrentFrame;
237
- config.mouseUpClientX = this.clientX;
238
- config.mouseUpClientY = this.clientY;
239
- }
240
- }
241
- };
242
-
243
- /**
244
- * Cleanup all animations.
245
- * @param skipPaint Only cleanup data or also clean up the canvas
246
- * @param forceClean Clean the canvas or not
247
- */
248
- cleanupAnimation = (skipPaint?: boolean, forceClean?: boolean) => {
249
- for (let i = 0; i < this.animationQueue.length; i++) {
250
- const config = this.animationQueue[i];
251
-
252
- this.cleanUpAnimationUnit(config, skipPaint, forceClean);
253
- }
254
- }
255
-
256
- /**
257
- * Clean up the config of an animation, but the canvas won't cleaned up.
258
- * @param config The config to be cleaned up.
259
- * @param skipPaint Skip painting.
260
- * @param forceClean Force clear the painting.
261
- */
262
- cleanUpAnimationUnit = (config: Config, skipPaint?: boolean, forceClean?: boolean) => {
263
- config.mouseUpClientX = null;
264
- config.mouseUpClientY = null;
265
- config.mouseDownAnimateStartFrame = null;
266
- config.mouseDownAnimateCurrentFrame = null;
267
- config.mouseDownAnimateReleasedFrame = null;
268
- config.mouseDownAnimateLogicFrame = null;
269
- config.mousePressed = false;
270
- config.mouseReleased = false;
271
-
272
- const configIdx = this.animationQueue.indexOf(config);
273
- if (configIdx > -1) {
274
- this.animationQueue.splice(configIdx, 1);
275
- }
276
-
277
- if (!skipPaint) {
278
- if (forceClean) {
279
- config.clear(false);
280
- } else if (this.mouseInBoundary) {
281
- config.paint(true);
282
- } else {
283
- config.clear(true);
284
- }
285
- }
286
- };
287
-
288
- getRevealAnimationConfig = () => {
289
- return this.canvasList.find((x) => x.mouseInCanvas()) || null;
290
- };
291
- }
1
+ import { CanvasConfig } from './CanvasConfig.js';
2
+ import { SvgConfig } from './SvgConfig.js';
3
+
4
+ type Config = CanvasConfig | SvgConfig;
5
+
6
+ export class RevealBoundaryStore {
7
+ id: number;
8
+ container: HTMLElement;
9
+
10
+ // The current cursor position relative to window.
11
+ clientX = -1000;
12
+ clientY = -1000;
13
+
14
+ // The cursor position of painted reveal effect.
15
+ paintedClientX = -1000;
16
+ paintedClientY = -1000;
17
+
18
+ mouseInBoundary = false;
19
+ canvasList: Config[] = [];
20
+
21
+ animationQueue: Config[] = [];
22
+ animationFrame: number | null = null;
23
+
24
+ mouseUpClientX = null;
25
+ mouseUpClientY = null;
26
+ mouseDownAnimateStartFrame = null;
27
+ mouseDownAnimateCurrentFrame = null;
28
+ mouseDownAnimateReleasedFrame = null;
29
+ mouseDownAnimateLogicFrame = null;
30
+ mousePressed = false;
31
+ mouseReleased = false;
32
+
33
+ maxRadius = -1;
34
+
35
+ requestedAnimationFrame = false;
36
+
37
+ constructor(id: number, $el: HTMLElement) {
38
+ this.id = id;
39
+ this.container = $el;
40
+ }
41
+
42
+ addReveal = ($element: HTMLCanvasElement | SVGElement, $container: HTMLElement) => {
43
+ let config: Config;
44
+ const elementType = Object.prototype.toString.call($element);
45
+
46
+ if (elementType === '[object HTMLCanvasElement]') {
47
+ config = new CanvasConfig(this, $element as HTMLCanvasElement, $container);
48
+ } else if (elementType === '[object SVGSVGElement]') {
49
+ config = new SvgConfig(this, $element as SVGSVGElement, $container);
50
+ } else {
51
+ throw new TypeError(`Unknown element type, got: ${elementType}, Canvas or SVG element expected.`)
52
+ }
53
+
54
+ config.cacheBoundingRect();
55
+ config.cacheCanvasPaintingStyle();
56
+ config.updateCachedBitmap();
57
+
58
+ this.canvasList.push(config);
59
+ };
60
+
61
+ removeReveal = ($el: HTMLCanvasElement | SVGElement) => {
62
+ this.canvasList = this.canvasList.filter((config) => {
63
+ return config && config.element !== $el;
64
+ });
65
+ };
66
+
67
+ updateMaxRadius = (x: number) => {
68
+ this.maxRadius = Math.max(x, this.maxRadius);
69
+ };
70
+
71
+ requestPaintAll = (cleanup?: boolean) => {
72
+ if (this.requestedAnimationFrame) return;
73
+ this.requestedAnimationFrame = true;
74
+
75
+ this.animationFrame = window.requestAnimationFrame((frame) => {
76
+ this.requestedAnimationFrame = false;
77
+ this.paintAll(cleanup ? -1 : frame, true);
78
+ });
79
+ };
80
+
81
+ updatePointerPosition = (x: number, y: number) => {
82
+ this.clientX = x;
83
+ this.clientY = y;
84
+
85
+ const boundingBox = this.container.getBoundingClientRect();
86
+
87
+ let mouseInBoundary = true;
88
+
89
+ if (x < boundingBox.left - this.maxRadius) mouseInBoundary = false;
90
+ if (x > boundingBox.right + this.maxRadius) mouseInBoundary = false;
91
+ if (y < boundingBox.top - this.maxRadius) mouseInBoundary = false;
92
+ if (y > boundingBox.bottom + this.maxRadius) mouseInBoundary = false;
93
+
94
+ this.mouseInBoundary = mouseInBoundary;
95
+ }
96
+
97
+ // While the browser scrolls under a finger, the finger stays on the same
98
+ // spot of the content, but touch events are throttled (~200ms in Chromium).
99
+ // The pointer is kept relative to the container and re-derived on every
100
+ // frame, otherwise it stays still on the screen while the content moves.
101
+ private anchorOffsetX: number | null = null;
102
+ private anchorOffsetY: number | null = null;
103
+
104
+ anchorPointer = () => {
105
+ const boundingBox = this.container.getBoundingClientRect();
106
+ this.anchorOffsetX = this.clientX - boundingBox.left;
107
+ this.anchorOffsetY = this.clientY - boundingBox.top;
108
+ };
109
+
110
+ private followAnchor = () => {
111
+ if (this.anchorOffsetX === null || this.anchorOffsetY === null) return;
112
+ const boundingBox = this.container.getBoundingClientRect();
113
+ this.clientX = boundingBox.left + this.anchorOffsetX;
114
+ this.clientY = boundingBox.top + this.anchorOffsetY;
115
+ };
116
+
117
+ onPointerMoveOnScreen = (x: number, y: number) => {
118
+ this.updatePointerPosition(x, y);
119
+ if (!this.mouseInBoundary) return;
120
+ this.requestPaintAll();
121
+ return true;
122
+ };
123
+
124
+ /**
125
+ * Repaint all canvas while user's pointer has entered the boundary.
126
+ */
127
+ onPointerEnterBoundary = () => {
128
+ this.mouseInBoundary = true;
129
+
130
+ if (!this.animationFrame) {
131
+ this.requestPaintAll();
132
+ }
133
+ };
134
+
135
+ /**
136
+ * Clear all canvas while user's pointer leave the bounary.
137
+ */
138
+ onPointerLeaveBoundary = () => {
139
+ this.anchorOffsetX = null;
140
+ this.anchorOffsetY = null;
141
+ this.mouseInBoundary = false;
142
+ this.requestPaintAll(true);
143
+ };
144
+
145
+ /**
146
+ * The painting method that draw everything on your screen.
147
+ * @param frame current frame index, if this value is 0, it means all canvas
148
+ * should be cleaned.
149
+ * @param skipSamePointerPositionCheck Literally.
150
+ */
151
+ private paintAll = (frame: number, skipSamePointerPositionCheck?: boolean) => {
152
+ if (!skipSamePointerPositionCheck && !this.mouseInBoundary && this.animationQueue.length === 0) {
153
+ return;
154
+ }
155
+
156
+ this.followAnchor();
157
+
158
+ // Animation duration checkup
159
+ for (let i = 0; i < this.animationQueue.length; i++) {
160
+ const config = this.animationQueue[i];
161
+
162
+ if (!frame || config.currentFrameId === frame) {
163
+ continue;
164
+ }
165
+
166
+ config.currentFrameId = frame;
167
+
168
+ // Initialize the animation parameter
169
+ if (config.mouseDownAnimateStartFrame === null) {
170
+ config.mouseDownAnimateStartFrame = frame;
171
+ }
172
+
173
+ // Calculate how long the animation has been playing
174
+ const relativeFrame = frame - config.mouseDownAnimateStartFrame;
175
+ config.mouseDownAnimateCurrentFrame = relativeFrame;
176
+
177
+ const speed = config.cachedStyle.pressAnimationSpeed;
178
+ const accelerateRate = config.cachedStyle.releaseAnimationAccelerateRate;
179
+
180
+ // We assume that Ripple is a one-way linear process from
181
+ // no diffusion to fully diffused,
182
+ // and Logic Frame represents the progress of the animation
183
+ // in this process.
184
+ let unitLogicFrame = relativeFrame;
185
+ if (config.mouseReleased && config.mouseDownAnimateReleasedFrame) {
186
+ unitLogicFrame += (relativeFrame - config.mouseDownAnimateReleasedFrame) * accelerateRate;
187
+ }
188
+ config.mouseDownAnimateLogicFrame = unitLogicFrame / speed;
189
+
190
+ if (config.mouseDownAnimateLogicFrame > 1) {
191
+ // It will be cleaned later
192
+ config.cleanedUpForAnimation = true;
193
+ }
194
+ }
195
+
196
+ // Paint the canvas one by one
197
+ for (let i = 0; i < this.canvasList.length; i++) {
198
+ const config = this.canvasList[i];
199
+ config.currentFrameId = frame;
200
+
201
+ if (config.cleanedUpForAnimation) {
202
+ this.cleanUpAnimationUnit(config, false);
203
+ config.cleanedUpForAnimation = false;
204
+ } else {
205
+ const isPlayingAnimation = this.animationQueue.indexOf(config) === -1;
206
+
207
+ if (this.mouseInBoundary || isPlayingAnimation) {
208
+ config.paint(skipSamePointerPositionCheck);
209
+ } else {
210
+ config.clear(false);
211
+ }
212
+ }
213
+ }
214
+
215
+ this.paintedClientX = this.clientX;
216
+ this.paintedClientY = this.clientY;
217
+
218
+ if (this.mouseInBoundary || this.animationQueue.length !== 0) {
219
+ this.requestPaintAll();
220
+ } else {
221
+ this.animationFrame = null;
222
+ }
223
+ };
224
+
225
+ /**
226
+ * Clear all canvas.
227
+ */
228
+ clearAll = (forAnimation: boolean) => {
229
+ this.cleanupAnimation(forAnimation, true);
230
+ };
231
+
232
+ /**
233
+ * This is the effect while user pressed on the reveal highlight,
234
+ * the ripple start to spread slowly.
235
+ */
236
+ initializeAnimation = () => {
237
+ const config = this.canvasList.find((x) => x.mouseInCanvas());
238
+
239
+ if (!config) return;
240
+
241
+ if (!this.animationQueue.includes(config)) {
242
+ this.animationQueue.push(config);
243
+ }
244
+
245
+ config.mouseDownAnimateStartFrame = null;
246
+ config.mousePressed = true;
247
+ config.mouseReleased = false;
248
+ };
249
+
250
+ /**
251
+ * This is the effect while user released it's pointer, the spreading
252
+ * ripple animation will start to accelerate.
253
+ */
254
+ switchAnimation = () => {
255
+ for (let i = 0; i < this.animationQueue.length; i++) {
256
+ const config = this.animationQueue[i];
257
+
258
+ if (!config.mouseReleased) {
259
+ config.mouseReleased = true;
260
+ config.mouseDownAnimateReleasedFrame = config.mouseDownAnimateCurrentFrame;
261
+ config.mouseUpClientX = this.clientX;
262
+ config.mouseUpClientY = this.clientY;
263
+ }
264
+ }
265
+ };
266
+
267
+ /**
268
+ * Cleanup all animations.
269
+ * @param skipPaint Only cleanup data or also clean up the canvas
270
+ * @param forceClean Clean the canvas or not
271
+ */
272
+ cleanupAnimation = (skipPaint?: boolean, forceClean?: boolean) => {
273
+ for (let i = 0; i < this.animationQueue.length; i++) {
274
+ const config = this.animationQueue[i];
275
+
276
+ this.cleanUpAnimationUnit(config, skipPaint, forceClean);
277
+ }
278
+ }
279
+
280
+ /**
281
+ * Clean up the config of an animation, but the canvas won't cleaned up.
282
+ * @param config The config to be cleaned up.
283
+ * @param skipPaint Skip painting.
284
+ * @param forceClean Force clear the painting.
285
+ */
286
+ cleanUpAnimationUnit = (config: Config, skipPaint?: boolean, forceClean?: boolean) => {
287
+ config.mouseUpClientX = null;
288
+ config.mouseUpClientY = null;
289
+ config.mouseDownAnimateStartFrame = null;
290
+ config.mouseDownAnimateCurrentFrame = null;
291
+ config.mouseDownAnimateReleasedFrame = null;
292
+ config.mouseDownAnimateLogicFrame = null;
293
+ config.mousePressed = false;
294
+ config.mouseReleased = false;
295
+
296
+ const configIdx = this.animationQueue.indexOf(config);
297
+ if (configIdx > -1) {
298
+ this.animationQueue.splice(configIdx, 1);
299
+ }
300
+
301
+ if (!skipPaint) {
302
+ if (forceClean) {
303
+ config.clear(false);
304
+ } else if (this.mouseInBoundary) {
305
+ config.paint(true);
306
+ } else {
307
+ config.clear(true);
308
+ }
309
+ }
310
+ };
311
+
312
+ getRevealAnimationConfig = () => {
313
+ return this.canvasList.find((x) => x.mouseInCanvas()) || null;
314
+ };
315
+ }