@visactor/vrender-animate 1.0.12 → 1.0.13

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 (80) hide show
  1. package/cjs/custom/disappear/base/CustomEffectBase.d.ts +32 -0
  2. package/cjs/custom/disappear/base/CustomEffectBase.js +81 -0
  3. package/cjs/custom/disappear/base/CustomEffectBase.js.map +1 -0
  4. package/cjs/custom/disappear/base/DisappearAnimateBase.d.ts +34 -0
  5. package/cjs/custom/disappear/base/DisappearAnimateBase.js +138 -0
  6. package/cjs/custom/disappear/base/DisappearAnimateBase.js.map +1 -0
  7. package/cjs/custom/disappear/base/ImageProcessUtils.d.ts +20 -0
  8. package/cjs/custom/disappear/base/ImageProcessUtils.js +80 -0
  9. package/cjs/custom/disappear/base/ImageProcessUtils.js.map +1 -0
  10. package/cjs/custom/disappear/dissolve.d.ts +27 -0
  11. package/cjs/custom/disappear/dissolve.js +237 -0
  12. package/cjs/custom/disappear/dissolve.js.map +1 -0
  13. package/cjs/custom/disappear/distortion.d.ts +22 -0
  14. package/cjs/custom/disappear/distortion.js +120 -0
  15. package/cjs/custom/disappear/distortion.js.map +1 -0
  16. package/cjs/custom/disappear/gaussian-blur.d.ts +13 -0
  17. package/cjs/custom/disappear/gaussian-blur.js +65 -0
  18. package/cjs/custom/disappear/gaussian-blur.js.map +1 -0
  19. package/cjs/custom/disappear/glitch.d.ts +20 -0
  20. package/cjs/custom/disappear/glitch.js +161 -0
  21. package/cjs/custom/disappear/glitch.js.map +1 -0
  22. package/cjs/custom/disappear/grayscale.d.ts +23 -0
  23. package/cjs/custom/disappear/grayscale.js +126 -0
  24. package/cjs/custom/disappear/grayscale.js.map +1 -0
  25. package/cjs/custom/disappear/particle.d.ts +49 -0
  26. package/cjs/custom/disappear/particle.js +191 -0
  27. package/cjs/custom/disappear/particle.js.map +1 -0
  28. package/cjs/custom/disappear/pixelation.d.ts +13 -0
  29. package/cjs/custom/disappear/pixelation.js +48 -0
  30. package/cjs/custom/disappear/pixelation.js.map +1 -0
  31. package/cjs/custom/register.d.ts +8 -1
  32. package/cjs/custom/register.js +72 -2
  33. package/cjs/custom/register.js.map +1 -1
  34. package/cjs/custom/richtext/input-richtext.js +1 -1
  35. package/cjs/custom/richtext/output-richtext.js +1 -1
  36. package/cjs/custom/richtext/slide-out-richtext.js +1 -1
  37. package/cjs/step.d.ts +0 -1
  38. package/cjs/step.js +0 -2
  39. package/cjs/step.js.map +1 -1
  40. package/dist/index.es.js +2251 -4
  41. package/es/custom/disappear/base/CustomEffectBase.d.ts +32 -0
  42. package/es/custom/disappear/base/CustomEffectBase.js +69 -0
  43. package/es/custom/disappear/base/CustomEffectBase.js.map +1 -0
  44. package/es/custom/disappear/base/DisappearAnimateBase.d.ts +34 -0
  45. package/es/custom/disappear/base/DisappearAnimateBase.js +132 -0
  46. package/es/custom/disappear/base/DisappearAnimateBase.js.map +1 -0
  47. package/es/custom/disappear/base/ImageProcessUtils.d.ts +20 -0
  48. package/es/custom/disappear/base/ImageProcessUtils.js +72 -0
  49. package/es/custom/disappear/base/ImageProcessUtils.js.map +1 -0
  50. package/es/custom/disappear/dissolve.d.ts +27 -0
  51. package/es/custom/disappear/dissolve.js +231 -0
  52. package/es/custom/disappear/dissolve.js.map +1 -0
  53. package/es/custom/disappear/distortion.d.ts +22 -0
  54. package/es/custom/disappear/distortion.js +112 -0
  55. package/es/custom/disappear/distortion.js.map +1 -0
  56. package/es/custom/disappear/gaussian-blur.d.ts +13 -0
  57. package/es/custom/disappear/gaussian-blur.js +59 -0
  58. package/es/custom/disappear/gaussian-blur.js.map +1 -0
  59. package/es/custom/disappear/glitch.d.ts +20 -0
  60. package/es/custom/disappear/glitch.js +155 -0
  61. package/es/custom/disappear/glitch.js.map +1 -0
  62. package/es/custom/disappear/grayscale.d.ts +23 -0
  63. package/es/custom/disappear/grayscale.js +117 -0
  64. package/es/custom/disappear/grayscale.js.map +1 -0
  65. package/es/custom/disappear/particle.d.ts +49 -0
  66. package/es/custom/disappear/particle.js +185 -0
  67. package/es/custom/disappear/particle.js.map +1 -0
  68. package/es/custom/disappear/pixelation.d.ts +13 -0
  69. package/es/custom/disappear/pixelation.js +42 -0
  70. package/es/custom/disappear/pixelation.js.map +1 -0
  71. package/es/custom/register.d.ts +8 -1
  72. package/es/custom/register.js +20 -2
  73. package/es/custom/register.js.map +1 -1
  74. package/es/custom/richtext/input-richtext.js +1 -1
  75. package/es/custom/richtext/output-richtext.js +1 -1
  76. package/es/custom/richtext/slide-out-richtext.js +1 -1
  77. package/es/step.d.ts +0 -1
  78. package/es/step.js +0 -2
  79. package/es/step.js.map +1 -1
  80. package/package.json +4 -4
package/dist/index.es.js CHANGED
@@ -1,4 +1,4 @@
1
- import { interpolateColor, interpolatePureColorArrayToStr, pointsInterpolation, Generator, ColorStore, ColorType, AnimateStatus, AnimateStepType, PerformanceRAF, STATUS, application, CustomPath2D, CurveContext, Graphic, splitRect, splitArc, splitCircle, splitLine, splitPolygon, splitArea, splitPath, AttributeUpdateType, pathToBezierCurves, applyTransformOnBezierCurves, alignBezierCurves, findBestMorphingRotation, pointInterpolation, RichText, divideCubic } from '@visactor/vrender-core';
1
+ import { interpolateColor, interpolatePureColorArrayToStr, pointsInterpolation, Generator, ColorStore, ColorType, AnimateStatus, AnimateStepType, PerformanceRAF, STATUS, application, CustomPath2D, CurveContext, Graphic, splitRect, splitArc, splitCircle, splitLine, splitPolygon, splitArea, splitPath, AttributeUpdateType, pathToBezierCurves, applyTransformOnBezierCurves, alignBezierCurves, findBestMorphingRotation, pointInterpolation, RichText, divideCubic, vglobal } from '@visactor/vrender-core';
2
2
  import { pi2, isString, EventEmitter, isArray, isFunction, mixin, isNil, isValidNumber, clamp, Point, pi, isNumber, isValid, isNumberClose, PointService } from '@visactor/vutils';
3
3
 
4
4
  class Easing {
@@ -565,8 +565,6 @@ class WaitStep extends Step {
565
565
  }
566
566
  onStart() {
567
567
  super.onStart();
568
- }
569
- onFirstRun() {
570
568
  const fromProps = this.getFromProps();
571
569
  this.target.setAttributes(fromProps);
572
570
  }
@@ -7156,6 +7154,2248 @@ class StreamLight extends ACustomAnimate {
7156
7154
  }
7157
7155
  }
7158
7156
 
7157
+ class DisappearAnimateBase extends AStageAnimate {
7158
+ constructor(from, to, duration, easing, params) {
7159
+ super(from, to, duration, easing, params);
7160
+ this.webglCanvas = null;
7161
+ this.gl = null;
7162
+ this.program = null;
7163
+ this.currentAnimationRatio = 0;
7164
+ this.animationTime = 0;
7165
+ }
7166
+ onUpdate(end, ratio, out) {
7167
+ super.onUpdate(end, ratio, out);
7168
+ this.currentAnimationRatio = ratio;
7169
+ this.animationTime = ratio * Math.PI * 2;
7170
+ }
7171
+ getAnimationTime() {
7172
+ if (this.currentAnimationRatio > 0) {
7173
+ return this.animationTime;
7174
+ }
7175
+ return Date.now() / 1000.0;
7176
+ }
7177
+ getDurationFromParent() {
7178
+ return this.duration || 1000;
7179
+ }
7180
+ initWebGL(canvas) {
7181
+ try {
7182
+ this.webglCanvas = vglobal.createCanvas({
7183
+ width: canvas.width,
7184
+ height: canvas.height,
7185
+ dpr: vglobal.devicePixelRatio
7186
+ });
7187
+ if (!this.webglCanvas) {
7188
+ console.warn('WebGL canvas creation failed');
7189
+ return false;
7190
+ }
7191
+ this.webglCanvas.style.width = canvas.style.width || `${canvas.width}px`;
7192
+ this.webglCanvas.style.height = canvas.style.height || `${canvas.height}px`;
7193
+ let glContext = null;
7194
+ try {
7195
+ glContext = this.webglCanvas.getContext('webgl');
7196
+ if (!glContext) {
7197
+ glContext = this.webglCanvas.getContext('experimental-webgl');
7198
+ }
7199
+ }
7200
+ catch (e) {
7201
+ console.warn('Failed to get WebGL context:', e);
7202
+ }
7203
+ this.gl = glContext;
7204
+ if (!this.gl) {
7205
+ console.warn('WebGL not supported');
7206
+ return false;
7207
+ }
7208
+ const shaders = this.getShaderSources();
7209
+ this.program = this.createShaderProgram(shaders.vertex, shaders.fragment);
7210
+ return this.program !== null;
7211
+ }
7212
+ catch (error) {
7213
+ console.warn('Failed to initialize WebGL:', error);
7214
+ return false;
7215
+ }
7216
+ }
7217
+ createShaderProgram(vertexSource, fragmentSource) {
7218
+ if (!this.gl) {
7219
+ return null;
7220
+ }
7221
+ const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource);
7222
+ const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);
7223
+ if (!vertexShader || !fragmentShader) {
7224
+ return null;
7225
+ }
7226
+ const program = this.gl.createProgram();
7227
+ if (!program) {
7228
+ return null;
7229
+ }
7230
+ this.gl.attachShader(program, vertexShader);
7231
+ this.gl.attachShader(program, fragmentShader);
7232
+ this.gl.linkProgram(program);
7233
+ if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
7234
+ console.error('Shader program link error:', this.gl.getProgramInfoLog(program));
7235
+ return null;
7236
+ }
7237
+ return program;
7238
+ }
7239
+ createShader(type, source) {
7240
+ if (!this.gl) {
7241
+ return null;
7242
+ }
7243
+ const shader = this.gl.createShader(type);
7244
+ if (!shader) {
7245
+ return null;
7246
+ }
7247
+ this.gl.shaderSource(shader, source);
7248
+ this.gl.compileShader(shader);
7249
+ if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
7250
+ console.error('Shader compile error:', this.gl.getShaderInfoLog(shader));
7251
+ this.gl.deleteShader(shader);
7252
+ return null;
7253
+ }
7254
+ return shader;
7255
+ }
7256
+ setupWebGLState(canvas) {
7257
+ if (!this.gl || !this.webglCanvas) {
7258
+ return;
7259
+ }
7260
+ if (this.webglCanvas.width !== canvas.width || this.webglCanvas.height !== canvas.height) {
7261
+ this.webglCanvas.width = canvas.width;
7262
+ this.webglCanvas.height = canvas.height;
7263
+ }
7264
+ this.gl.viewport(0, 0, this.webglCanvas.width, this.webglCanvas.height);
7265
+ this.gl.clearColor(0.0, 0.0, 0.0, 0.0);
7266
+ this.gl.clear(this.gl.COLOR_BUFFER_BIT);
7267
+ }
7268
+ createFullScreenQuad() {
7269
+ if (!this.gl) {
7270
+ return null;
7271
+ }
7272
+ const vertices = new Float32Array([
7273
+ -1,
7274
+ -1,
7275
+ 0,
7276
+ 1,
7277
+ 1,
7278
+ -1,
7279
+ 1,
7280
+ 1,
7281
+ -1,
7282
+ 1,
7283
+ 0,
7284
+ 0,
7285
+ 1,
7286
+ 1,
7287
+ 1,
7288
+ 0
7289
+ ]);
7290
+ const vertexBuffer = this.gl.createBuffer();
7291
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer);
7292
+ this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);
7293
+ return vertexBuffer;
7294
+ }
7295
+ createTextureFromCanvas(canvas) {
7296
+ if (!this.gl) {
7297
+ return null;
7298
+ }
7299
+ const texture = this.gl.createTexture();
7300
+ this.gl.activeTexture(this.gl.TEXTURE0);
7301
+ this.gl.bindTexture(this.gl.TEXTURE_2D, texture);
7302
+ this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, canvas);
7303
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE);
7304
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE);
7305
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
7306
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
7307
+ return texture;
7308
+ }
7309
+ setupVertexAttributes() {
7310
+ if (!this.gl || !this.program) {
7311
+ return;
7312
+ }
7313
+ const positionLocation = this.gl.getAttribLocation(this.program, 'a_position');
7314
+ const texCoordLocation = this.gl.getAttribLocation(this.program, 'a_texCoord');
7315
+ this.gl.enableVertexAttribArray(positionLocation);
7316
+ this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 16, 0);
7317
+ this.gl.enableVertexAttribArray(texCoordLocation);
7318
+ this.gl.vertexAttribPointer(texCoordLocation, 2, this.gl.FLOAT, false, 16, 8);
7319
+ }
7320
+ createOutputCanvas(canvas) {
7321
+ const outputCanvas = vglobal.createCanvas({
7322
+ width: canvas.width,
7323
+ height: canvas.height,
7324
+ dpr: vglobal.devicePixelRatio
7325
+ });
7326
+ const ctx = outputCanvas.getContext('2d');
7327
+ if (!ctx) {
7328
+ return null;
7329
+ }
7330
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
7331
+ ctx.drawImage(canvas, 0, 0);
7332
+ return { canvas: outputCanvas, ctx };
7333
+ }
7334
+ getShaderSources() {
7335
+ return null;
7336
+ }
7337
+ applyWebGLEffect(canvas) {
7338
+ return null;
7339
+ }
7340
+ applyCanvas2DEffect(canvas) {
7341
+ return null;
7342
+ }
7343
+ supportsWebGL() {
7344
+ return this.getShaderSources() !== null;
7345
+ }
7346
+ supportsCanvas2D() {
7347
+ return this.applyCanvas2DEffect !== DisappearAnimateBase.prototype.applyCanvas2DEffect;
7348
+ }
7349
+ release() {
7350
+ super.release();
7351
+ if (this.gl) {
7352
+ if (this.program) {
7353
+ this.gl.deleteProgram(this.program);
7354
+ this.program = null;
7355
+ }
7356
+ this.gl = null;
7357
+ }
7358
+ if (this.webglCanvas) {
7359
+ this.webglCanvas = null;
7360
+ }
7361
+ this.currentAnimationRatio = 0;
7362
+ this.animationTime = 0;
7363
+ }
7364
+ afterStageRender(stage, canvas) {
7365
+ let result = null;
7366
+ if (this.supportsWebGL()) {
7367
+ if (!this.gl && !this.initWebGL(canvas)) {
7368
+ console.warn('WebGL初始化失败,尝试Canvas 2D回退');
7369
+ }
7370
+ if (this.gl) {
7371
+ result = this.applyWebGLEffect(canvas);
7372
+ if (result) {
7373
+ return result;
7374
+ }
7375
+ console.warn('WebGL特效执行失败,尝试Canvas 2D回退');
7376
+ }
7377
+ }
7378
+ if (this.supportsCanvas2D()) {
7379
+ result = this.applyCanvas2DEffect(canvas);
7380
+ if (result) {
7381
+ return result;
7382
+ }
7383
+ console.warn('Canvas 2D特效执行失败');
7384
+ }
7385
+ if (!this.supportsWebGL() && !this.supportsCanvas2D()) {
7386
+ console.error(`特效类 ${this.constructor.name} 未实现任何渲染方法。请实现 applyWebGLEffect 或 applyCanvas2DEffect 方法。`);
7387
+ }
7388
+ return canvas;
7389
+ }
7390
+ }
7391
+
7392
+ class Canvas2DEffectBase extends DisappearAnimateBase {
7393
+ constructor(from, to, duration, easing, params) {
7394
+ super(from, to, duration, easing, params);
7395
+ }
7396
+ getShaderSources() {
7397
+ return null;
7398
+ }
7399
+ applyWebGLEffect(canvas) {
7400
+ return null;
7401
+ }
7402
+ }
7403
+ class HybridEffectBase extends DisappearAnimateBase {
7404
+ constructor(from, to, duration, easing, params) {
7405
+ super(from, to, duration, easing, params);
7406
+ }
7407
+ getShaderSources() {
7408
+ return null;
7409
+ }
7410
+ applyWebGLEffect(canvas) {
7411
+ return null;
7412
+ }
7413
+ applyCanvas2DEffect(canvas) {
7414
+ return null;
7415
+ }
7416
+ supportsWebGL() {
7417
+ return this.getShaderSources !== HybridEffectBase.prototype.getShaderSources && this.getShaderSources() !== null;
7418
+ }
7419
+ supportsCanvas2D() {
7420
+ return this.applyCanvas2DEffect !== HybridEffectBase.prototype.applyCanvas2DEffect;
7421
+ }
7422
+ afterStageRender(stage, canvas) {
7423
+ var _a, _b;
7424
+ let result = null;
7425
+ if (((_b = (_a = this.params) === null || _a === void 0 ? void 0 : _a.options) === null || _b === void 0 ? void 0 : _b.useWebGL) !== false) {
7426
+ if (this.supportsWebGL()) {
7427
+ if (!this.gl && !this.initWebGL(canvas)) {
7428
+ console.warn('WebGL初始化失败,尝试Canvas 2D回退');
7429
+ }
7430
+ if (this.gl) {
7431
+ result = this.applyWebGLEffect(canvas);
7432
+ if (result) {
7433
+ return result;
7434
+ }
7435
+ console.warn('WebGL特效执行失败,尝试Canvas 2D回退');
7436
+ }
7437
+ }
7438
+ if (this.supportsCanvas2D()) {
7439
+ result = this.applyCanvas2DEffect(canvas);
7440
+ if (result) {
7441
+ return result;
7442
+ }
7443
+ console.warn('Canvas 2D特效执行失败');
7444
+ }
7445
+ }
7446
+ else {
7447
+ if (this.supportsCanvas2D()) {
7448
+ result = this.applyCanvas2DEffect(canvas);
7449
+ if (result) {
7450
+ return result;
7451
+ }
7452
+ console.warn('Canvas 2D特效执行失败');
7453
+ }
7454
+ else {
7455
+ console.warn(`${this.constructor.name}: useWebGL=false 但未实现Canvas 2D方法`);
7456
+ }
7457
+ }
7458
+ if (!this.supportsWebGL() && !this.supportsCanvas2D()) {
7459
+ console.error(`特效类 ${this.constructor.name} 未实现任何渲染方法。请实现 applyWebGLEffect 或 applyCanvas2DEffect 方法。`);
7460
+ }
7461
+ return canvas;
7462
+ }
7463
+ }
7464
+
7465
+ class ImageProcessUtils {
7466
+ static createTempCanvas(width, height, dpr) {
7467
+ return vglobal.createCanvas({
7468
+ width,
7469
+ height,
7470
+ dpr: dpr || vglobal.devicePixelRatio
7471
+ });
7472
+ }
7473
+ static cloneImageData(imageData) {
7474
+ const clonedData = new Uint8ClampedArray(imageData.data);
7475
+ return new ImageData(clonedData, imageData.width, imageData.height);
7476
+ }
7477
+ static lerp(start, end, t) {
7478
+ return start * (1 - t) + end * t;
7479
+ }
7480
+ static smoothstep(edge0, edge1, x) {
7481
+ const t = Math.max(0, Math.min(1, (x - edge0) / (edge1 - edge0)));
7482
+ return t * t * (3 - 2 * t);
7483
+ }
7484
+ static distance(x1, y1, x2, y2) {
7485
+ const dx = x2 - x1;
7486
+ const dy = y2 - y1;
7487
+ return Math.sqrt(dx * dx + dy * dy);
7488
+ }
7489
+ static normalizeAngle(angle) {
7490
+ return (angle + Math.PI) / (2 * Math.PI);
7491
+ }
7492
+ static pixelNoise(x, y, pixelSize) {
7493
+ if (pixelSize <= 0) {
7494
+ return 0;
7495
+ }
7496
+ const gridX = Math.floor(x / pixelSize) * pixelSize;
7497
+ const gridY = Math.floor(y / pixelSize) * pixelSize;
7498
+ const n = Math.sin(gridX * 12.9898 + gridY * 78.233) * 43758.5453;
7499
+ return n - Math.floor(n);
7500
+ }
7501
+ static generateNoiseTexture(width, height) {
7502
+ const data = new Uint8Array(width * height);
7503
+ for (let i = 0; i < data.length; i++) {
7504
+ data[i] = Math.floor(Math.random() * 256);
7505
+ }
7506
+ return data;
7507
+ }
7508
+ static applyCSSFilter(canvas, filter) {
7509
+ const outputCanvas = this.createTempCanvas(canvas.width, canvas.height);
7510
+ const ctx = outputCanvas.getContext('2d');
7511
+ if (!ctx) {
7512
+ return canvas;
7513
+ }
7514
+ ctx.filter = filter;
7515
+ ctx.drawImage(canvas, 0, 0);
7516
+ ctx.filter = 'none';
7517
+ return outputCanvas;
7518
+ }
7519
+ static extractChannel(imageData, channelIndex) {
7520
+ const { data, width, height } = imageData;
7521
+ const channelData = new Uint8ClampedArray(data.length);
7522
+ for (let i = 0; i < data.length; i += 4) {
7523
+ channelData[i] = 0;
7524
+ channelData[i + 1] = 0;
7525
+ channelData[i + 2] = 0;
7526
+ channelData[i + 3] = data[i + 3];
7527
+ if (channelIndex >= 0 && channelIndex <= 2) {
7528
+ channelData[i + channelIndex] = data[i + channelIndex];
7529
+ }
7530
+ }
7531
+ return new ImageData(channelData, width, height);
7532
+ }
7533
+ static blendImageData(imageData1, imageData2, ratio) {
7534
+ const { data: data1, width, height } = imageData1;
7535
+ const { data: data2 } = imageData2;
7536
+ const result = new Uint8ClampedArray(data1.length);
7537
+ for (let i = 0; i < data1.length; i += 4) {
7538
+ result[i] = Math.round(this.lerp(data1[i], data2[i], ratio));
7539
+ result[i + 1] = Math.round(this.lerp(data1[i + 1], data2[i + 1], ratio));
7540
+ result[i + 2] = Math.round(this.lerp(data1[i + 2], data2[i + 2], ratio));
7541
+ result[i + 3] = Math.round(this.lerp(data1[i + 3], data2[i + 3], ratio));
7542
+ }
7543
+ return new ImageData(result, width, height);
7544
+ }
7545
+ static getLuminance(r, g, b) {
7546
+ return r * 0.299 + g * 0.587 + b * 0.114;
7547
+ }
7548
+ static applySepiaToPixel(r, g, b) {
7549
+ const sepiaR = Math.min(255, r * 0.393 + g * 0.769 + b * 0.189);
7550
+ const sepiaG = Math.min(255, r * 0.349 + g * 0.686 + b * 0.168);
7551
+ const sepiaB = Math.min(255, r * 0.272 + g * 0.534 + b * 0.131);
7552
+ return [sepiaR, sepiaG, sepiaB];
7553
+ }
7554
+ static calculateDynamicStrength(baseStrength, animationTime) {
7555
+ return baseStrength * (animationTime / (Math.PI * 2));
7556
+ }
7557
+ }
7558
+ class ShaderLibrary {
7559
+ }
7560
+ ShaderLibrary.STANDARD_VERTEX_SHADER = `
7561
+ attribute vec2 a_position;
7562
+ attribute vec2 a_texCoord;
7563
+ varying vec2 v_texCoord;
7564
+
7565
+ void main() {
7566
+ gl_Position = vec4(a_position, 0.0, 1.0);
7567
+ v_texCoord = a_texCoord;
7568
+ }
7569
+ `;
7570
+ ShaderLibrary.SHADER_FUNCTIONS = `
7571
+ // 亮度计算函数
7572
+ float luminance(vec3 color) {
7573
+ return dot(color, vec3(0.299, 0.587, 0.114));
7574
+ }
7575
+
7576
+ // 褐色调函数
7577
+ vec3 sepia(vec3 color) {
7578
+ float r = color.r * 0.393 + color.g * 0.769 + color.b * 0.189;
7579
+ float g = color.r * 0.349 + color.g * 0.686 + color.b * 0.168;
7580
+ float b = color.r * 0.272 + color.g * 0.534 + color.b * 0.131;
7581
+ return vec3(r, g, b);
7582
+ }
7583
+
7584
+ // 线性插值函数
7585
+ float lerp(float a, float b, float t) {
7586
+ return a * (1.0 - t) + b * t;
7587
+ }
7588
+
7589
+
7590
+ // 简单噪声函数
7591
+ float pixelNoise(vec2 coord, float pixelSize) {
7592
+ vec2 gridCoord = floor(coord / pixelSize) * pixelSize;
7593
+ return fract(sin(dot(gridCoord, vec2(12.9898, 78.233))) * 43758.5453123);
7594
+ }
7595
+
7596
+ // 动态强度计算
7597
+ float calculateDynamicStrength(float baseStrength, float time) {
7598
+ return baseStrength * (time / 6.28318531); // 2π
7599
+ }
7600
+ `;
7601
+
7602
+ class Dissolve extends HybridEffectBase {
7603
+ constructor(from, to, duration, easing, params) {
7604
+ var _a, _b, _c, _d;
7605
+ super(from, to, duration, easing, params);
7606
+ this.noiseData = null;
7607
+ const rawNoiseScale = (_a = params === null || params === void 0 ? void 0 : params.options) === null || _a === void 0 ? void 0 : _a.noiseScale;
7608
+ const clampedNoiseScale = rawNoiseScale !== undefined ? Math.max(0, Math.floor(rawNoiseScale)) : 8;
7609
+ this.dissolveConfig = {
7610
+ dissolveType: ((_b = params === null || params === void 0 ? void 0 : params.options) === null || _b === void 0 ? void 0 : _b.dissolveType) || 'outward',
7611
+ useWebGL: ((_c = params === null || params === void 0 ? void 0 : params.options) === null || _c === void 0 ? void 0 : _c.useWebGL) !== undefined ? params.options.useWebGL : true,
7612
+ noiseScale: clampedNoiseScale,
7613
+ fadeEdge: ((_d = params === null || params === void 0 ? void 0 : params.options) === null || _d === void 0 ? void 0 : _d.fadeEdge) !== undefined ? params.options.fadeEdge : true
7614
+ };
7615
+ }
7616
+ getShaderSources() {
7617
+ const vertexShader = ShaderLibrary.STANDARD_VERTEX_SHADER;
7618
+ const fragmentShader = `
7619
+ precision mediump float;
7620
+ uniform sampler2D u_texture;
7621
+ uniform sampler2D u_noiseTexture;
7622
+ uniform float u_time;
7623
+ uniform int u_dissolveType;
7624
+ uniform vec2 u_resolution;
7625
+ uniform float u_noiseScale;
7626
+ uniform bool u_fadeEdge;
7627
+ varying vec2 v_texCoord;
7628
+
7629
+ ${ShaderLibrary.SHADER_FUNCTIONS}
7630
+
7631
+ // 向外溶解函数
7632
+ float outwardDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {
7633
+ vec2 center = vec2(0.5, 0.5);
7634
+ float distFromCenter = length(uv - center);
7635
+ float maxDist = length(vec2(0.5, 0.5));
7636
+
7637
+ // 归一化距离 (0为中心,1为边缘)
7638
+ float normalizedDist = distFromCenter / maxDist;
7639
+
7640
+ // 向外溶解:从边缘开始溶解,time控制溶解进度
7641
+ // 增加安全边距,确保动画结束时完全溶解
7642
+ float edgeThreshold = 1.2 - time * 1.5;
7643
+
7644
+ // 当pixelSize > 0时添加颗粒效果
7645
+ if (pixelSize > 0.0) {
7646
+ // 添加基于像素大小的噪声,让边缘呈现颗粒状
7647
+ vec2 pixelCoord = uv * resolution; // 转换为像素坐标
7648
+ float noiseValue = pixelNoise(pixelCoord, pixelSize);
7649
+ float noiseInfluence = (noiseValue - 0.5) * 0.4; // 增强噪声影响
7650
+ edgeThreshold += noiseInfluence;
7651
+ return normalizedDist > edgeThreshold ? 0.0 : 1.0;
7652
+ } else {
7653
+ // 平滑溶解:根据fadeEdge决定是否使用渐变
7654
+ if (u_fadeEdge) {
7655
+ // 柔和边缘:返回渐变值
7656
+ float fadeWidth = 0.15; // 渐变宽度
7657
+ return 1.0 - smoothstep(edgeThreshold - fadeWidth, edgeThreshold, normalizedDist);
7658
+ } else {
7659
+ // 硬边缘:返回0或1
7660
+ return normalizedDist > edgeThreshold ? 0.0 : 1.0;
7661
+ }
7662
+ }
7663
+ }
7664
+
7665
+ // 向内溶解函数
7666
+ float inwardDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {
7667
+ vec2 center = vec2(0.5, 0.5);
7668
+ float distFromCenter = length(uv - center);
7669
+ float maxDist = length(vec2(0.5, 0.5));
7670
+
7671
+ float normalizedDist = distFromCenter / maxDist;
7672
+
7673
+ // 向内溶解:从中心开始溶解,time控制溶解进度
7674
+ // 增加系数,确保动画结束时完全溶解
7675
+ float centerThreshold = time * 1.4;
7676
+
7677
+ // 当pixelSize > 0时添加颗粒效果
7678
+ if (pixelSize > 0.0) {
7679
+ vec2 pixelCoord = uv * resolution;
7680
+ float noiseValue = pixelNoise(pixelCoord, pixelSize);
7681
+ float noiseInfluence = (noiseValue - 0.5) * 0.4;
7682
+ centerThreshold += noiseInfluence;
7683
+ return normalizedDist < centerThreshold ? 0.0 : 1.0;
7684
+ } else {
7685
+ // 平滑溶解:根据fadeEdge决定是否使用渐变
7686
+ if (u_fadeEdge) {
7687
+ // 柔和边缘:返回渐变值
7688
+ float fadeWidth = 0.15; // 渐变宽度
7689
+ return smoothstep(centerThreshold, centerThreshold + fadeWidth, normalizedDist);
7690
+ } else {
7691
+ // 硬边缘:返回0或1
7692
+ return normalizedDist < centerThreshold ? 0.0 : 1.0;
7693
+ }
7694
+ }
7695
+ }
7696
+
7697
+ // 径向溶解函数
7698
+ float radialDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {
7699
+ vec2 center = vec2(0.5, 0.5);
7700
+ float angle = atan(uv.y - center.y, uv.x - center.x);
7701
+ float normalizedAngle = (angle + 3.14159) / (2.0 * 3.14159);
7702
+
7703
+ // 径向溶解:按角度顺序溶解,time控制溶解进度
7704
+ // 增加系数,确保动画结束时完全溶解
7705
+ float angleThreshold = time * 1.2;
7706
+
7707
+ // 当pixelSize > 0时添加颗粒效果
7708
+ if (pixelSize > 0.0) {
7709
+ vec2 pixelCoord = uv * resolution;
7710
+ float noiseValue = pixelNoise(pixelCoord, pixelSize);
7711
+ float noiseInfluence = (noiseValue - 0.5) * 0.3;
7712
+ angleThreshold += noiseInfluence;
7713
+ return normalizedAngle < angleThreshold ? 0.0 : 1.0;
7714
+ } else {
7715
+ // 平滑溶解:根据fadeEdge决定是否使用渐变
7716
+ if (u_fadeEdge) {
7717
+ // 柔和边缘:返回渐变值
7718
+ float fadeWidth = 0.08; // 渐变宽度
7719
+ return smoothstep(angleThreshold, angleThreshold + fadeWidth, normalizedAngle);
7720
+ } else {
7721
+ // 硬边缘:返回0或1
7722
+ return normalizedAngle < angleThreshold ? 0.0 : 1.0;
7723
+ }
7724
+ }
7725
+ }
7726
+
7727
+ // 从左到右溶解函数
7728
+ float leftToRightDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {
7729
+ // 左到右溶解:从x=0开始向x=1溶解
7730
+ float dissolvePosition = time * 1.2; // 增加系数确保完全溶解
7731
+
7732
+ // 当pixelSize > 0时添加颗粒效果
7733
+ if (pixelSize > 0.0) {
7734
+ vec2 pixelCoord = uv * resolution;
7735
+ float noiseValue = pixelNoise(pixelCoord, pixelSize);
7736
+ float noiseInfluence = (noiseValue - 0.5) * 0.3;
7737
+ dissolvePosition += noiseInfluence;
7738
+ return uv.x < dissolvePosition ? 0.0 : 1.0;
7739
+ } else {
7740
+ // 平滑溶解:根据fadeEdge决定是否使用渐变
7741
+ if (u_fadeEdge) {
7742
+ // 柔和边缘:返回渐变值
7743
+ float fadeWidth = 0.08; // 渐变宽度
7744
+ return smoothstep(dissolvePosition, dissolvePosition + fadeWidth, uv.x);
7745
+ } else {
7746
+ // 硬边缘:返回0或1
7747
+ return uv.x < dissolvePosition ? 0.0 : 1.0;
7748
+ }
7749
+ }
7750
+ }
7751
+
7752
+ // 从右到左溶解函数
7753
+ float rightToLeftDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {
7754
+ // 右到左溶解:从x=1开始向x=0溶解
7755
+ float dissolvePosition = 1.0 - time * 1.2; // 增加系数确保完全溶解
7756
+
7757
+ // 当pixelSize > 0时添加颗粒效果
7758
+ if (pixelSize > 0.0) {
7759
+ vec2 pixelCoord = uv * resolution;
7760
+ float noiseValue = pixelNoise(pixelCoord, pixelSize);
7761
+ float noiseInfluence = (noiseValue - 0.5) * 0.3;
7762
+ dissolvePosition += noiseInfluence;
7763
+ return uv.x > dissolvePosition ? 0.0 : 1.0;
7764
+ } else {
7765
+ // 平滑溶解:根据fadeEdge决定是否使用渐变
7766
+ if (u_fadeEdge) {
7767
+ // 柔和边缘:返回渐变值
7768
+ float fadeWidth = 0.08; // 渐变宽度
7769
+ return smoothstep(dissolvePosition - fadeWidth, dissolvePosition, uv.x);
7770
+ } else {
7771
+ // 硬边缘:返回0或1
7772
+ return uv.x > dissolvePosition ? 0.0 : 1.0;
7773
+ }
7774
+ }
7775
+ }
7776
+
7777
+ // 从上到下溶解函数
7778
+ float topToBottomDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {
7779
+ // 上到下溶解:从y=0开始向y=1溶解
7780
+ float dissolvePosition = time * 1.2; // 增加系数确保完全溶解
7781
+
7782
+ // 当pixelSize > 0时添加颗粒效果
7783
+ if (pixelSize > 0.0) {
7784
+ vec2 pixelCoord = uv * resolution;
7785
+ float noiseValue = pixelNoise(pixelCoord, pixelSize);
7786
+ float noiseInfluence = (noiseValue - 0.5) * 0.3;
7787
+ dissolvePosition += noiseInfluence;
7788
+ return uv.y < dissolvePosition ? 0.0 : 1.0;
7789
+ } else {
7790
+ // 平滑溶解:根据fadeEdge决定是否使用渐变
7791
+ if (u_fadeEdge) {
7792
+ // 柔和边缘:返回渐变值
7793
+ float fadeWidth = 0.08; // 渐变宽度
7794
+ return smoothstep(dissolvePosition, dissolvePosition + fadeWidth, uv.y);
7795
+ } else {
7796
+ // 硬边缘:返回0或1
7797
+ return uv.y < dissolvePosition ? 0.0 : 1.0;
7798
+ }
7799
+ }
7800
+ }
7801
+
7802
+ // 从下到上溶解函数
7803
+ float bottomToTopDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {
7804
+ // 下到上溶解:从y=1开始向y=0溶解
7805
+ float dissolvePosition = 1.0 - time * 1.2; // 增加系数确保完全溶解
7806
+
7807
+ // 当pixelSize > 0时添加颗粒效果
7808
+ if (pixelSize > 0.0) {
7809
+ vec2 pixelCoord = uv * resolution;
7810
+ float noiseValue = pixelNoise(pixelCoord, pixelSize);
7811
+ float noiseInfluence = (noiseValue - 0.5) * 0.3;
7812
+ dissolvePosition += noiseInfluence;
7813
+ return uv.y > dissolvePosition ? 0.0 : 1.0;
7814
+ } else {
7815
+ // 平滑溶解:根据fadeEdge决定是否使用渐变
7816
+ if (u_fadeEdge) {
7817
+ // 柔和边缘:返回渐变值
7818
+ float fadeWidth = 0.08; // 渐变宽度
7819
+ return smoothstep(dissolvePosition - fadeWidth, dissolvePosition, uv.y);
7820
+ } else {
7821
+ // 硬边缘:返回0或1
7822
+ return uv.y > dissolvePosition ? 0.0 : 1.0;
7823
+ }
7824
+ }
7825
+ }
7826
+
7827
+ void main() {
7828
+ vec2 uv = v_texCoord;
7829
+ vec4 texColor = texture2D(u_texture, uv);
7830
+
7831
+ float alpha = 1.0;
7832
+
7833
+ // 根据溶解类型选择对应的溶解函数
7834
+ if (u_dissolveType == 0) {
7835
+ alpha = outwardDissolve(uv, u_time, u_noiseScale, u_resolution);
7836
+ } else if (u_dissolveType == 1) {
7837
+ alpha = inwardDissolve(uv, u_time, u_noiseScale, u_resolution);
7838
+ } else if (u_dissolveType == 2) {
7839
+ alpha = radialDissolve(uv, u_time, u_noiseScale, u_resolution);
7840
+ } else if (u_dissolveType == 3) {
7841
+ alpha = leftToRightDissolve(uv, u_time, u_noiseScale, u_resolution);
7842
+ } else if (u_dissolveType == 4) {
7843
+ alpha = rightToLeftDissolve(uv, u_time, u_noiseScale, u_resolution);
7844
+ } else if (u_dissolveType == 5) {
7845
+ alpha = topToBottomDissolve(uv, u_time, u_noiseScale, u_resolution);
7846
+ } else if (u_dissolveType == 6) {
7847
+ alpha = bottomToTopDissolve(uv, u_time, u_noiseScale, u_resolution);
7848
+ }
7849
+
7850
+ gl_FragColor = vec4(texColor.rgb, texColor.a * alpha);
7851
+ }
7852
+ `;
7853
+ return { vertex: vertexShader, fragment: fragmentShader };
7854
+ }
7855
+ applyWebGLEffect(canvas) {
7856
+ if (!this.gl || !this.program || !this.webglCanvas) {
7857
+ return canvas;
7858
+ }
7859
+ this.setupWebGLState(canvas);
7860
+ const texture = this.createTextureFromCanvas(canvas);
7861
+ if (!texture) {
7862
+ return canvas;
7863
+ }
7864
+ if (!this.noiseData) {
7865
+ this.noiseData = ImageProcessUtils.generateNoiseTexture(256, 256);
7866
+ }
7867
+ const noiseTexture = this.gl.createTexture();
7868
+ this.gl.activeTexture(this.gl.TEXTURE1);
7869
+ this.gl.bindTexture(this.gl.TEXTURE_2D, noiseTexture);
7870
+ this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.LUMINANCE, 256, 256, 0, this.gl.LUMINANCE, this.gl.UNSIGNED_BYTE, this.noiseData);
7871
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.REPEAT);
7872
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.REPEAT);
7873
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR);
7874
+ this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
7875
+ const vertexBuffer = this.createFullScreenQuad();
7876
+ if (!vertexBuffer) {
7877
+ return canvas;
7878
+ }
7879
+ this.gl.useProgram(this.program);
7880
+ this.setupVertexAttributes();
7881
+ this.setUniforms();
7882
+ this.gl.enable(this.gl.BLEND);
7883
+ this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
7884
+ this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
7885
+ this.gl.deleteTexture(texture);
7886
+ this.gl.deleteTexture(noiseTexture);
7887
+ this.gl.deleteBuffer(vertexBuffer);
7888
+ return this.webglCanvas;
7889
+ }
7890
+ setUniforms() {
7891
+ if (!this.gl || !this.program || !this.webglCanvas) {
7892
+ return;
7893
+ }
7894
+ const textureLocation = this.gl.getUniformLocation(this.program, 'u_texture');
7895
+ const noiseTextureLocation = this.gl.getUniformLocation(this.program, 'u_noiseTexture');
7896
+ const timeLocation = this.gl.getUniformLocation(this.program, 'u_time');
7897
+ const dissolveTypeLocation = this.gl.getUniformLocation(this.program, 'u_dissolveType');
7898
+ const resolutionLocation = this.gl.getUniformLocation(this.program, 'u_resolution');
7899
+ const noiseScaleLocation = this.gl.getUniformLocation(this.program, 'u_noiseScale');
7900
+ const fadeEdgeLocation = this.gl.getUniformLocation(this.program, 'u_fadeEdge');
7901
+ this.gl.uniform1i(textureLocation, 0);
7902
+ this.gl.uniform1i(noiseTextureLocation, 1);
7903
+ this.gl.uniform1f(timeLocation, this.currentAnimationRatio);
7904
+ this.gl.uniform2f(resolutionLocation, this.webglCanvas.width, this.webglCanvas.height);
7905
+ this.gl.uniform1f(noiseScaleLocation, this.dissolveConfig.noiseScale);
7906
+ this.gl.uniform1i(fadeEdgeLocation, this.dissolveConfig.fadeEdge ? 1 : 0);
7907
+ const dissolveTypeMap = {
7908
+ outward: 0,
7909
+ inward: 1,
7910
+ radial: 2,
7911
+ leftToRight: 3,
7912
+ rightToLeft: 4,
7913
+ topToBottom: 5,
7914
+ bottomToTop: 6
7915
+ };
7916
+ this.gl.uniform1i(dissolveTypeLocation, dissolveTypeMap[this.dissolveConfig.dissolveType] || 0);
7917
+ }
7918
+ applyCanvas2DEffect(canvas) {
7919
+ const outputCanvas = this.createOutputCanvas(canvas);
7920
+ if (!outputCanvas) {
7921
+ return canvas;
7922
+ }
7923
+ const { canvas: outputCanvasElement, ctx } = outputCanvas;
7924
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
7925
+ const progress = this.currentAnimationRatio;
7926
+ let dissolvedImageData;
7927
+ switch (this.dissolveConfig.dissolveType) {
7928
+ case 'outward':
7929
+ dissolvedImageData = this.applyOutwardDissolve(imageData, progress);
7930
+ break;
7931
+ case 'inward':
7932
+ dissolvedImageData = this.applyInwardDissolve(imageData, progress);
7933
+ break;
7934
+ case 'radial':
7935
+ dissolvedImageData = this.applyRadialDissolve(imageData, progress);
7936
+ break;
7937
+ case 'leftToRight':
7938
+ dissolvedImageData = this.applyLeftToRightDissolve(imageData, progress);
7939
+ break;
7940
+ case 'rightToLeft':
7941
+ dissolvedImageData = this.applyRightToLeftDissolve(imageData, progress);
7942
+ break;
7943
+ case 'topToBottom':
7944
+ dissolvedImageData = this.applyTopToBottomDissolve(imageData, progress);
7945
+ break;
7946
+ case 'bottomToTop':
7947
+ dissolvedImageData = this.applyBottomToTopDissolve(imageData, progress);
7948
+ break;
7949
+ default:
7950
+ dissolvedImageData = imageData;
7951
+ }
7952
+ ctx.putImageData(dissolvedImageData, 0, 0);
7953
+ return outputCanvasElement;
7954
+ }
7955
+ applyOutwardDissolve(imageData, progress) {
7956
+ const { data, width, height } = imageData;
7957
+ const result = new Uint8ClampedArray(data.length);
7958
+ result.set(data);
7959
+ const centerX = width / 2;
7960
+ const centerY = height / 2;
7961
+ const maxDist = Math.sqrt(centerX * centerX + centerY * centerY);
7962
+ const pixelSize = this.dissolveConfig.noiseScale;
7963
+ for (let y = 0; y < height; y++) {
7964
+ for (let x = 0; x < width; x++) {
7965
+ const dx = x - centerX;
7966
+ const dy = y - centerY;
7967
+ const distFromCenter = Math.sqrt(dx * dx + dy * dy);
7968
+ const normalizedDist = distFromCenter / maxDist;
7969
+ let dissolveThreshold = 1.2 - progress * 1.4;
7970
+ let alpha = 1.0;
7971
+ if (pixelSize > 0) {
7972
+ const noiseValue = ImageProcessUtils.pixelNoise(x, y, pixelSize);
7973
+ const noiseInfluence = (noiseValue - 0.5) * 0.4;
7974
+ dissolveThreshold += noiseInfluence;
7975
+ alpha = normalizedDist > dissolveThreshold ? 0.0 : 1.0;
7976
+ }
7977
+ else {
7978
+ if (this.dissolveConfig.fadeEdge) {
7979
+ const fadeWidth = 0.15;
7980
+ const fadeStart = dissolveThreshold - fadeWidth;
7981
+ const fadeEnd = dissolveThreshold;
7982
+ if (normalizedDist < fadeStart) {
7983
+ alpha = 1.0;
7984
+ }
7985
+ else if (normalizedDist > fadeEnd) {
7986
+ alpha = 0.0;
7987
+ }
7988
+ else {
7989
+ alpha = 1.0 - (normalizedDist - fadeStart) / (fadeEnd - fadeStart);
7990
+ }
7991
+ }
7992
+ else {
7993
+ alpha = normalizedDist > dissolveThreshold ? 0.0 : 1.0;
7994
+ }
7995
+ }
7996
+ const index = (y * width + x) * 4;
7997
+ result[index + 3] = Math.floor(result[index + 3] * alpha);
7998
+ }
7999
+ }
8000
+ return new ImageData(result, width, height);
8001
+ }
8002
+ applyInwardDissolve(imageData, progress) {
8003
+ const { data, width, height } = imageData;
8004
+ const result = new Uint8ClampedArray(data.length);
8005
+ result.set(data);
8006
+ const centerX = width / 2;
8007
+ const centerY = height / 2;
8008
+ const maxDist = Math.sqrt(centerX * centerX + centerY * centerY);
8009
+ const pixelSize = this.dissolveConfig.noiseScale;
8010
+ for (let y = 0; y < height; y++) {
8011
+ for (let x = 0; x < width; x++) {
8012
+ const dx = x - centerX;
8013
+ const dy = y - centerY;
8014
+ const distFromCenter = Math.sqrt(dx * dx + dy * dy);
8015
+ const normalizedDist = distFromCenter / maxDist;
8016
+ let dissolveThreshold = progress * 1.4;
8017
+ let alpha = 1.0;
8018
+ if (pixelSize > 0) {
8019
+ const noiseValue = ImageProcessUtils.pixelNoise(x, y, pixelSize);
8020
+ const noiseInfluence = (noiseValue - 0.5) * 0.4;
8021
+ dissolveThreshold += noiseInfluence;
8022
+ alpha = normalizedDist < dissolveThreshold ? 0.0 : 1.0;
8023
+ }
8024
+ else {
8025
+ if (this.dissolveConfig.fadeEdge) {
8026
+ const fadeWidth = 0.15;
8027
+ const fadeStart = dissolveThreshold;
8028
+ const fadeEnd = dissolveThreshold + fadeWidth;
8029
+ if (normalizedDist < fadeStart) {
8030
+ alpha = 0.0;
8031
+ }
8032
+ else if (normalizedDist > fadeEnd) {
8033
+ alpha = 1.0;
8034
+ }
8035
+ else {
8036
+ alpha = (normalizedDist - fadeStart) / (fadeEnd - fadeStart);
8037
+ }
8038
+ }
8039
+ else {
8040
+ alpha = normalizedDist < dissolveThreshold ? 0.0 : 1.0;
8041
+ }
8042
+ }
8043
+ const index = (y * width + x) * 4;
8044
+ result[index + 3] = Math.floor(result[index + 3] * alpha);
8045
+ }
8046
+ }
8047
+ return new ImageData(result, width, height);
8048
+ }
8049
+ applyRadialDissolve(imageData, progress) {
8050
+ const { data, width, height } = imageData;
8051
+ const result = new Uint8ClampedArray(data.length);
8052
+ result.set(data);
8053
+ const centerX = width / 2;
8054
+ const centerY = height / 2;
8055
+ const pixelSize = this.dissolveConfig.noiseScale;
8056
+ for (let y = 0; y < height; y++) {
8057
+ for (let x = 0; x < width; x++) {
8058
+ const dx = x - centerX;
8059
+ const dy = y - centerY;
8060
+ const angle = Math.atan2(dy, dx);
8061
+ const normalizedAngle = (angle + Math.PI) / (2 * Math.PI);
8062
+ let dissolveThreshold = progress * 1.2;
8063
+ let alpha = 1.0;
8064
+ if (pixelSize > 0) {
8065
+ const noiseValue = ImageProcessUtils.pixelNoise(x, y, pixelSize);
8066
+ const noiseInfluence = (noiseValue - 0.5) * 0.3;
8067
+ dissolveThreshold += noiseInfluence;
8068
+ alpha = normalizedAngle < dissolveThreshold ? 0.0 : 1.0;
8069
+ }
8070
+ else {
8071
+ if (this.dissolveConfig.fadeEdge) {
8072
+ const fadeWidth = 0.08;
8073
+ const fadeStart = dissolveThreshold;
8074
+ const fadeEnd = dissolveThreshold + fadeWidth;
8075
+ if (normalizedAngle < fadeStart) {
8076
+ alpha = 0.0;
8077
+ }
8078
+ else if (normalizedAngle > fadeEnd) {
8079
+ alpha = 1.0;
8080
+ }
8081
+ else {
8082
+ alpha = (normalizedAngle - fadeStart) / (fadeEnd - fadeStart);
8083
+ }
8084
+ }
8085
+ else {
8086
+ alpha = normalizedAngle < dissolveThreshold ? 0.0 : 1.0;
8087
+ }
8088
+ }
8089
+ const index = (y * width + x) * 4;
8090
+ result[index + 3] = Math.floor(result[index + 3] * alpha);
8091
+ }
8092
+ }
8093
+ return new ImageData(result, width, height);
8094
+ }
8095
+ applyLeftToRightDissolve(imageData, progress) {
8096
+ const { data, width, height } = imageData;
8097
+ const result = new Uint8ClampedArray(data.length);
8098
+ result.set(data);
8099
+ const pixelSize = this.dissolveConfig.noiseScale;
8100
+ for (let y = 0; y < height; y++) {
8101
+ for (let x = 0; x < width; x++) {
8102
+ const normalizedX = x / width;
8103
+ let dissolveThreshold = progress * 1.2;
8104
+ let alpha = 1.0;
8105
+ if (pixelSize > 0) {
8106
+ const noiseValue = ImageProcessUtils.pixelNoise(x, y, pixelSize);
8107
+ const noiseInfluence = (noiseValue - 0.5) * 0.3;
8108
+ dissolveThreshold += noiseInfluence;
8109
+ alpha = normalizedX < dissolveThreshold ? 0.0 : 1.0;
8110
+ }
8111
+ else {
8112
+ if (this.dissolveConfig.fadeEdge) {
8113
+ const fadeWidth = 0.08;
8114
+ const fadeStart = dissolveThreshold;
8115
+ const fadeEnd = dissolveThreshold + fadeWidth;
8116
+ if (normalizedX < fadeStart) {
8117
+ alpha = 0.0;
8118
+ }
8119
+ else if (normalizedX > fadeEnd) {
8120
+ alpha = 1.0;
8121
+ }
8122
+ else {
8123
+ alpha = (normalizedX - fadeStart) / (fadeEnd - fadeStart);
8124
+ }
8125
+ }
8126
+ else {
8127
+ alpha = normalizedX < dissolveThreshold ? 0.0 : 1.0;
8128
+ }
8129
+ }
8130
+ const index = (y * width + x) * 4;
8131
+ result[index + 3] = Math.floor(result[index + 3] * alpha);
8132
+ }
8133
+ }
8134
+ return new ImageData(result, width, height);
8135
+ }
8136
+ applyRightToLeftDissolve(imageData, progress) {
8137
+ const { data, width, height } = imageData;
8138
+ const result = new Uint8ClampedArray(data.length);
8139
+ result.set(data);
8140
+ const pixelSize = this.dissolveConfig.noiseScale;
8141
+ for (let y = 0; y < height; y++) {
8142
+ for (let x = 0; x < width; x++) {
8143
+ const normalizedX = x / width;
8144
+ let dissolveThreshold = 1.0 - progress * 1.2;
8145
+ let alpha = 1.0;
8146
+ if (pixelSize > 0) {
8147
+ const noiseValue = ImageProcessUtils.pixelNoise(x, y, pixelSize);
8148
+ const noiseInfluence = (noiseValue - 0.5) * 0.3;
8149
+ dissolveThreshold += noiseInfluence;
8150
+ alpha = normalizedX > dissolveThreshold ? 0.0 : 1.0;
8151
+ }
8152
+ else {
8153
+ if (this.dissolveConfig.fadeEdge) {
8154
+ const fadeWidth = 0.08;
8155
+ const fadeStart = dissolveThreshold - fadeWidth;
8156
+ const fadeEnd = dissolveThreshold;
8157
+ if (normalizedX < fadeStart) {
8158
+ alpha = 1.0;
8159
+ }
8160
+ else if (normalizedX > fadeEnd) {
8161
+ alpha = 0.0;
8162
+ }
8163
+ else {
8164
+ alpha = 1.0 - (normalizedX - fadeStart) / (fadeEnd - fadeStart);
8165
+ }
8166
+ }
8167
+ else {
8168
+ alpha = normalizedX > dissolveThreshold ? 0.0 : 1.0;
8169
+ }
8170
+ }
8171
+ const index = (y * width + x) * 4;
8172
+ result[index + 3] = Math.floor(result[index + 3] * alpha);
8173
+ }
8174
+ }
8175
+ return new ImageData(result, width, height);
8176
+ }
8177
+ applyTopToBottomDissolve(imageData, progress) {
8178
+ const { data, width, height } = imageData;
8179
+ const result = new Uint8ClampedArray(data.length);
8180
+ result.set(data);
8181
+ const pixelSize = this.dissolveConfig.noiseScale;
8182
+ for (let y = 0; y < height; y++) {
8183
+ for (let x = 0; x < width; x++) {
8184
+ const normalizedY = y / height;
8185
+ let dissolveThreshold = progress * 1.2;
8186
+ let alpha = 1.0;
8187
+ if (pixelSize > 0) {
8188
+ const noiseValue = ImageProcessUtils.pixelNoise(x, y, pixelSize);
8189
+ const noiseInfluence = (noiseValue - 0.5) * 0.3;
8190
+ dissolveThreshold += noiseInfluence;
8191
+ alpha = normalizedY < dissolveThreshold ? 0.0 : 1.0;
8192
+ }
8193
+ else {
8194
+ if (this.dissolveConfig.fadeEdge) {
8195
+ const fadeWidth = 0.08;
8196
+ const fadeStart = dissolveThreshold;
8197
+ const fadeEnd = dissolveThreshold + fadeWidth;
8198
+ if (normalizedY < fadeStart) {
8199
+ alpha = 0.0;
8200
+ }
8201
+ else if (normalizedY > fadeEnd) {
8202
+ alpha = 1.0;
8203
+ }
8204
+ else {
8205
+ alpha = (normalizedY - fadeStart) / (fadeEnd - fadeStart);
8206
+ }
8207
+ }
8208
+ else {
8209
+ alpha = normalizedY < dissolveThreshold ? 0.0 : 1.0;
8210
+ }
8211
+ }
8212
+ const index = (y * width + x) * 4;
8213
+ result[index + 3] = Math.floor(result[index + 3] * alpha);
8214
+ }
8215
+ }
8216
+ return new ImageData(result, width, height);
8217
+ }
8218
+ applyBottomToTopDissolve(imageData, progress) {
8219
+ const { data, width, height } = imageData;
8220
+ const result = new Uint8ClampedArray(data.length);
8221
+ result.set(data);
8222
+ const pixelSize = this.dissolveConfig.noiseScale;
8223
+ for (let y = 0; y < height; y++) {
8224
+ for (let x = 0; x < width; x++) {
8225
+ const normalizedY = y / height;
8226
+ let dissolveThreshold = 1.0 - progress * 1.2;
8227
+ let alpha = 1.0;
8228
+ if (pixelSize > 0) {
8229
+ const noiseValue = ImageProcessUtils.pixelNoise(x, y, pixelSize);
8230
+ const noiseInfluence = (noiseValue - 0.5) * 0.3;
8231
+ dissolveThreshold += noiseInfluence;
8232
+ alpha = normalizedY > dissolveThreshold ? 0.0 : 1.0;
8233
+ }
8234
+ else {
8235
+ if (this.dissolveConfig.fadeEdge) {
8236
+ const fadeWidth = 0.08;
8237
+ const fadeStart = dissolveThreshold - fadeWidth;
8238
+ const fadeEnd = dissolveThreshold;
8239
+ if (normalizedY < fadeStart) {
8240
+ alpha = 1.0;
8241
+ }
8242
+ else if (normalizedY > fadeEnd) {
8243
+ alpha = 0.0;
8244
+ }
8245
+ else {
8246
+ alpha = 1.0 - (normalizedY - fadeStart) / (fadeEnd - fadeStart);
8247
+ }
8248
+ }
8249
+ else {
8250
+ alpha = normalizedY > dissolveThreshold ? 0.0 : 1.0;
8251
+ }
8252
+ }
8253
+ const index = (y * width + x) * 4;
8254
+ result[index + 3] = Math.floor(result[index + 3] * alpha);
8255
+ }
8256
+ }
8257
+ return new ImageData(result, width, height);
8258
+ }
8259
+ }
8260
+
8261
+ class Grayscale extends HybridEffectBase {
8262
+ constructor(from, to, duration, easing, params) {
8263
+ var _a, _b, _c;
8264
+ super(from, to, duration, easing, params);
8265
+ const rawStrength = ((_a = params === null || params === void 0 ? void 0 : params.options) === null || _a === void 0 ? void 0 : _a.strength) !== undefined ? params.options.strength : 1.0;
8266
+ const clampedStrength = Math.max(0, Math.min(1, rawStrength));
8267
+ this.colorConfig = {
8268
+ effectType: ((_b = params === null || params === void 0 ? void 0 : params.options) === null || _b === void 0 ? void 0 : _b.effectType) || 'grayscale',
8269
+ strength: clampedStrength,
8270
+ useWebGL: ((_c = params === null || params === void 0 ? void 0 : params.options) === null || _c === void 0 ? void 0 : _c.useWebGL) !== undefined ? params.options.useWebGL : true
8271
+ };
8272
+ }
8273
+ getShaderSources() {
8274
+ const vertexShader = ShaderLibrary.STANDARD_VERTEX_SHADER;
8275
+ const fragmentShader = `
8276
+ precision mediump float;
8277
+ uniform sampler2D u_texture;
8278
+ uniform float u_time;
8279
+ uniform float u_strength;
8280
+ uniform int u_effectType;
8281
+ uniform vec2 u_resolution;
8282
+ varying vec2 v_texCoord;
8283
+
8284
+ ${ShaderLibrary.SHADER_FUNCTIONS}
8285
+
8286
+ void main() {
8287
+ vec2 uv = v_texCoord;
8288
+ vec4 originalColor = texture2D(u_texture, uv);
8289
+ vec3 color = originalColor.rgb;
8290
+
8291
+ // 计算动态强度
8292
+ float dynamicStrength = calculateDynamicStrength(u_strength, u_time);
8293
+
8294
+ if (u_effectType == 0) {
8295
+ // 灰度效果
8296
+ float gray = luminance(color);
8297
+ vec3 grayColor = vec3(gray);
8298
+ color = mix(color, grayColor, dynamicStrength);
8299
+ } else if (u_effectType == 1) {
8300
+ // 褐色调效果
8301
+ vec3 sepiaColor = sepia(color);
8302
+ color = mix(color, sepiaColor, dynamicStrength);
8303
+ }
8304
+
8305
+ gl_FragColor = vec4(color, originalColor.a);
8306
+ }
8307
+ `;
8308
+ return { vertex: vertexShader, fragment: fragmentShader };
8309
+ }
8310
+ applyWebGLEffect(canvas) {
8311
+ if (!this.gl || !this.program || !this.webglCanvas) {
8312
+ return null;
8313
+ }
8314
+ this.setupWebGLState(canvas);
8315
+ const texture = this.createTextureFromCanvas(canvas);
8316
+ if (!texture) {
8317
+ return null;
8318
+ }
8319
+ const vertexBuffer = this.createFullScreenQuad();
8320
+ if (!vertexBuffer) {
8321
+ this.gl.deleteTexture(texture);
8322
+ return null;
8323
+ }
8324
+ try {
8325
+ this.gl.useProgram(this.program);
8326
+ this.setupVertexAttributes();
8327
+ this.setColorUniforms();
8328
+ this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
8329
+ return this.webglCanvas;
8330
+ }
8331
+ finally {
8332
+ this.gl.deleteTexture(texture);
8333
+ this.gl.deleteBuffer(vertexBuffer);
8334
+ }
8335
+ }
8336
+ setColorUniforms() {
8337
+ if (!this.gl || !this.program) {
8338
+ return;
8339
+ }
8340
+ const currentTime = this.getAnimationTime();
8341
+ const timeLocation = this.gl.getUniformLocation(this.program, 'u_time');
8342
+ const strengthLocation = this.gl.getUniformLocation(this.program, 'u_strength');
8343
+ const effectTypeLocation = this.gl.getUniformLocation(this.program, 'u_effectType');
8344
+ const resolutionLocation = this.gl.getUniformLocation(this.program, 'u_resolution');
8345
+ this.gl.uniform1f(timeLocation, currentTime);
8346
+ this.gl.uniform1f(strengthLocation, this.colorConfig.strength);
8347
+ this.gl.uniform2f(resolutionLocation, this.webglCanvas.width, this.webglCanvas.height);
8348
+ const effectTypeMap = {
8349
+ grayscale: 0,
8350
+ sepia: 1
8351
+ };
8352
+ this.gl.uniform1i(effectTypeLocation, effectTypeMap[this.colorConfig.effectType] || 0);
8353
+ }
8354
+ applyCanvas2DEffect(canvas) {
8355
+ if (this.colorConfig.strength <= 0) {
8356
+ const outputCanvas = this.createOutputCanvas(canvas);
8357
+ return outputCanvas ? outputCanvas.canvas : null;
8358
+ }
8359
+ if (this.canUseCSSFilter()) {
8360
+ return this.applyCSSFilter(canvas);
8361
+ }
8362
+ const outputCanvas = this.createOutputCanvas(canvas);
8363
+ if (!outputCanvas) {
8364
+ return null;
8365
+ }
8366
+ const { ctx } = outputCanvas;
8367
+ try {
8368
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
8369
+ const currentTime = this.getAnimationTime();
8370
+ let processedImageData;
8371
+ switch (this.colorConfig.effectType) {
8372
+ case 'grayscale':
8373
+ processedImageData = this.applyGrayscaleEffect(imageData, this.colorConfig.strength, currentTime);
8374
+ break;
8375
+ case 'sepia':
8376
+ processedImageData = this.applySepiaEffect(imageData, this.colorConfig.strength, currentTime);
8377
+ break;
8378
+ default:
8379
+ processedImageData = this.applyGrayscaleEffect(imageData, this.colorConfig.strength, currentTime);
8380
+ }
8381
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
8382
+ ctx.putImageData(processedImageData, 0, 0);
8383
+ return outputCanvas.canvas;
8384
+ }
8385
+ catch (error) {
8386
+ console.warn('Canvas 2D color effect failed:', error);
8387
+ return null;
8388
+ }
8389
+ }
8390
+ canUseCSSFilter() {
8391
+ var _a;
8392
+ return !!window.useFilterAPI && typeof CSS !== 'undefined' && ((_a = CSS.supports) === null || _a === void 0 ? void 0 : _a.call(CSS, 'filter', 'grayscale(1)'));
8393
+ }
8394
+ applyCSSFilter(canvas) {
8395
+ try {
8396
+ const outputCanvas = ImageProcessUtils.createTempCanvas(canvas.width, canvas.height);
8397
+ const ctx = outputCanvas.getContext('2d');
8398
+ if (!ctx) {
8399
+ return null;
8400
+ }
8401
+ const currentTime = this.getAnimationTime();
8402
+ const dynamicStrength = ImageProcessUtils.calculateDynamicStrength(this.colorConfig.strength, currentTime);
8403
+ let filterValue = '';
8404
+ if (this.colorConfig.effectType === 'grayscale') {
8405
+ filterValue = `grayscale(${Math.min(1, dynamicStrength)})`;
8406
+ }
8407
+ else if (this.colorConfig.effectType === 'sepia') {
8408
+ filterValue = `sepia(${Math.min(1, dynamicStrength)})`;
8409
+ }
8410
+ ctx.filter = filterValue;
8411
+ ctx.drawImage(canvas, 0, 0);
8412
+ ctx.filter = 'none';
8413
+ return outputCanvas;
8414
+ }
8415
+ catch (error) {
8416
+ console.warn('CSS Filter API failed, falling back to pixel processing:', error);
8417
+ return null;
8418
+ }
8419
+ }
8420
+ applyGrayscaleEffect(imageData, strength, time) {
8421
+ const { data, width, height } = imageData;
8422
+ const result = new Uint8ClampedArray(data.length);
8423
+ const dynamicStrength = ImageProcessUtils.calculateDynamicStrength(strength, time);
8424
+ for (let i = 0; i < data.length; i += 4) {
8425
+ const r = data[i];
8426
+ const g = data[i + 1];
8427
+ const b = data[i + 2];
8428
+ const a = data[i + 3];
8429
+ const gray = ImageProcessUtils.getLuminance(r, g, b);
8430
+ result[i] = Math.round(ImageProcessUtils.lerp(r, gray, dynamicStrength));
8431
+ result[i + 1] = Math.round(ImageProcessUtils.lerp(g, gray, dynamicStrength));
8432
+ result[i + 2] = Math.round(ImageProcessUtils.lerp(b, gray, dynamicStrength));
8433
+ result[i + 3] = a;
8434
+ }
8435
+ return new ImageData(result, width, height);
8436
+ }
8437
+ applySepiaEffect(imageData, strength, time) {
8438
+ const { data, width, height } = imageData;
8439
+ const result = new Uint8ClampedArray(data.length);
8440
+ const dynamicStrength = ImageProcessUtils.calculateDynamicStrength(strength, time);
8441
+ for (let i = 0; i < data.length; i += 4) {
8442
+ const r = data[i];
8443
+ const g = data[i + 1];
8444
+ const b = data[i + 2];
8445
+ const a = data[i + 3];
8446
+ const [sepiaR, sepiaG, sepiaB] = ImageProcessUtils.applySepiaToPixel(r, g, b);
8447
+ result[i] = Math.round(ImageProcessUtils.lerp(r, sepiaR, dynamicStrength));
8448
+ result[i + 1] = Math.round(ImageProcessUtils.lerp(g, sepiaG, dynamicStrength));
8449
+ result[i + 2] = Math.round(ImageProcessUtils.lerp(b, sepiaB, dynamicStrength));
8450
+ result[i + 3] = a;
8451
+ }
8452
+ return new ImageData(result, width, height);
8453
+ }
8454
+ afterStageRender(stage, canvas) {
8455
+ if (this.canUseCSSFilter() && this.colorConfig.strength > 0) {
8456
+ const cssResult = this.applyCSSFilter(canvas);
8457
+ if (cssResult) {
8458
+ return cssResult;
8459
+ }
8460
+ }
8461
+ return super.afterStageRender(stage, canvas);
8462
+ }
8463
+ }
8464
+
8465
+ class Distortion extends HybridEffectBase {
8466
+ constructor(from, to, duration, easing, params) {
8467
+ var _a, _b, _c;
8468
+ super(from, to, duration, easing, params);
8469
+ this.distortionConfig = {
8470
+ distortionType: ((_a = params === null || params === void 0 ? void 0 : params.options) === null || _a === void 0 ? void 0 : _a.distortionType) || 'wave',
8471
+ strength: ((_b = params === null || params === void 0 ? void 0 : params.options) === null || _b === void 0 ? void 0 : _b.strength) || 0.3,
8472
+ useWebGL: ((_c = params === null || params === void 0 ? void 0 : params.options) === null || _c === void 0 ? void 0 : _c.useWebGL) !== undefined ? params.options.useWebGL : true
8473
+ };
8474
+ }
8475
+ getShaderSources() {
8476
+ const vertexShader = `
8477
+ attribute vec2 a_position;
8478
+ attribute vec2 a_texCoord;
8479
+ varying vec2 v_texCoord;
8480
+
8481
+ void main() {
8482
+ gl_Position = vec4(a_position, 0.0, 1.0);
8483
+ v_texCoord = a_texCoord;
8484
+ }
8485
+ `;
8486
+ const fragmentShader = `
8487
+ precision mediump float;
8488
+ uniform sampler2D u_texture;
8489
+ uniform float u_time;
8490
+ uniform float u_strength;
8491
+ uniform int u_distortionType;
8492
+ uniform vec2 u_resolution;
8493
+ varying vec2 v_texCoord;
8494
+
8495
+ // 波浪扭曲函数
8496
+ vec2 wave(vec2 uv, float time, float strength) {
8497
+ float waveX = sin(uv.y * 10.0 + time * 3.0) * strength * 0.1;
8498
+ float waveY = sin(uv.x * 10.0 + time * 2.0) * strength * 0.1;
8499
+ return uv + vec2(waveX, waveY);
8500
+ }
8501
+
8502
+ // 涟漪扭曲函数
8503
+ vec2 ripple(vec2 uv, float time, float strength) {
8504
+ vec2 center = vec2(0.5, 0.5);
8505
+ float distance = length(uv - center);
8506
+ float ripple = sin(distance * 20.0 - time * 5.0) * strength * 0.1;
8507
+ vec2 direction = normalize(uv - center);
8508
+ return uv + direction * ripple;
8509
+ }
8510
+
8511
+ // 漩涡扭曲函数
8512
+ vec2 swirl(vec2 uv, float time, float strength) {
8513
+ vec2 center = vec2(0.5, 0.5);
8514
+ vec2 delta = uv - center;
8515
+ float dist = length(delta);
8516
+ float originalAngle = atan(delta.y, delta.x);
8517
+ float rotationAngle = dist * strength * time * 2.0;
8518
+ float finalAngle = originalAngle + rotationAngle;
8519
+ return center + dist * vec2(cos(finalAngle), sin(finalAngle));
8520
+ }
8521
+
8522
+ void main() {
8523
+ vec2 uv = v_texCoord;
8524
+
8525
+ // 根据扭曲类型应用相应变换
8526
+ if (u_distortionType == 0) {
8527
+ uv = wave(uv, u_time, u_strength);
8528
+ } else if (u_distortionType == 1) {
8529
+ uv = ripple(uv, u_time, u_strength);
8530
+ } else if (u_distortionType == 2) {
8531
+ uv = swirl(uv, u_time, u_strength);
8532
+ }
8533
+
8534
+ // 边界检查
8535
+ if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {
8536
+ gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);
8537
+ } else {
8538
+ gl_FragColor = texture2D(u_texture, uv);
8539
+ }
8540
+ }
8541
+ `;
8542
+ return { vertex: vertexShader, fragment: fragmentShader };
8543
+ }
8544
+ applyWebGLEffect(canvas) {
8545
+ if (!this.gl || !this.program || !this.webglCanvas) {
8546
+ return null;
8547
+ }
8548
+ this.setupWebGLState(canvas);
8549
+ const texture = this.createTextureFromCanvas(canvas);
8550
+ if (!texture) {
8551
+ return null;
8552
+ }
8553
+ const vertexBuffer = this.createFullScreenQuad();
8554
+ if (!vertexBuffer) {
8555
+ this.gl.deleteTexture(texture);
8556
+ return null;
8557
+ }
8558
+ try {
8559
+ this.gl.useProgram(this.program);
8560
+ this.setupVertexAttributes();
8561
+ this.setDistortionUniforms();
8562
+ this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
8563
+ return this.webglCanvas;
8564
+ }
8565
+ finally {
8566
+ this.gl.deleteTexture(texture);
8567
+ this.gl.deleteBuffer(vertexBuffer);
8568
+ }
8569
+ }
8570
+ setDistortionUniforms() {
8571
+ if (!this.gl || !this.program) {
8572
+ return;
8573
+ }
8574
+ const currentTime = this.getAnimationTime();
8575
+ const timeLocation = this.gl.getUniformLocation(this.program, 'u_time');
8576
+ const strengthLocation = this.gl.getUniformLocation(this.program, 'u_strength');
8577
+ const distortionTypeLocation = this.gl.getUniformLocation(this.program, 'u_distortionType');
8578
+ const resolutionLocation = this.gl.getUniformLocation(this.program, 'u_resolution');
8579
+ this.gl.uniform1f(timeLocation, currentTime);
8580
+ this.gl.uniform1f(strengthLocation, this.distortionConfig.strength);
8581
+ this.gl.uniform2f(resolutionLocation, this.webglCanvas.width, this.webglCanvas.height);
8582
+ const distortionTypeMap = {
8583
+ wave: 0,
8584
+ ripple: 1,
8585
+ swirl: 2
8586
+ };
8587
+ this.gl.uniform1i(distortionTypeLocation, distortionTypeMap[this.distortionConfig.distortionType] || 0);
8588
+ }
8589
+ applyCanvas2DEffect(canvas) {
8590
+ const outputCanvas = this.createOutputCanvas(canvas);
8591
+ if (!outputCanvas) {
8592
+ return null;
8593
+ }
8594
+ const { ctx } = outputCanvas;
8595
+ try {
8596
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
8597
+ const currentTime = this.getAnimationTime();
8598
+ let distortedImageData;
8599
+ switch (this.distortionConfig.distortionType) {
8600
+ case 'wave':
8601
+ distortedImageData = this.applyWaveDistortion(imageData, this.distortionConfig.strength, currentTime);
8602
+ break;
8603
+ case 'ripple':
8604
+ distortedImageData = this.applyRippleDistortion(imageData, this.distortionConfig.strength, currentTime);
8605
+ break;
8606
+ case 'swirl':
8607
+ distortedImageData = this.applySwirlDistortion(imageData, this.distortionConfig.strength, currentTime);
8608
+ break;
8609
+ default:
8610
+ distortedImageData = imageData;
8611
+ }
8612
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
8613
+ ctx.putImageData(distortedImageData, 0, 0);
8614
+ return outputCanvas.canvas;
8615
+ }
8616
+ catch (error) {
8617
+ console.warn('Canvas 2D distortion effect failed:', error);
8618
+ return null;
8619
+ }
8620
+ }
8621
+ applyWaveDistortion(imageData, strength, time) {
8622
+ const { data, width, height } = imageData;
8623
+ const result = new Uint8ClampedArray(data.length);
8624
+ for (let y = 0; y < height; y++) {
8625
+ for (let x = 0; x < width; x++) {
8626
+ const waveX = Math.sin(y * 0.1 + time * 3) * strength * 20;
8627
+ const waveY = Math.sin(x * 0.1 + time * 2) * strength * 20;
8628
+ const sourceX = Math.round(x - waveX);
8629
+ const sourceY = Math.round(y - waveY);
8630
+ const targetIndex = (y * width + x) * 4;
8631
+ if (sourceX >= 0 && sourceX < width && sourceY >= 0 && sourceY < height) {
8632
+ const sourceIndex = (sourceY * width + sourceX) * 4;
8633
+ result[targetIndex] = data[sourceIndex];
8634
+ result[targetIndex + 1] = data[sourceIndex + 1];
8635
+ result[targetIndex + 2] = data[sourceIndex + 2];
8636
+ result[targetIndex + 3] = data[sourceIndex + 3];
8637
+ }
8638
+ else {
8639
+ result[targetIndex + 3] = 0;
8640
+ }
8641
+ }
8642
+ }
8643
+ return new ImageData(result, width, height);
8644
+ }
8645
+ applyRippleDistortion(imageData, strength, time) {
8646
+ const { data, width, height } = imageData;
8647
+ const result = new Uint8ClampedArray(data.length);
8648
+ const centerX = width / 2;
8649
+ const centerY = height / 2;
8650
+ for (let y = 0; y < height; y++) {
8651
+ for (let x = 0; x < width; x++) {
8652
+ const dx = x - centerX;
8653
+ const dy = y - centerY;
8654
+ const distance = Math.sqrt(dx * dx + dy * dy);
8655
+ const ripple = Math.sin(distance * 0.2 - time * 5) * strength * 10;
8656
+ const angle = Math.atan2(dy, dx);
8657
+ const sourceX = Math.round(x - Math.cos(angle) * ripple);
8658
+ const sourceY = Math.round(y - Math.sin(angle) * ripple);
8659
+ const targetIndex = (y * width + x) * 4;
8660
+ if (sourceX >= 0 && sourceX < width && sourceY >= 0 && sourceY < height) {
8661
+ const sourceIndex = (sourceY * width + sourceX) * 4;
8662
+ result[targetIndex] = data[sourceIndex];
8663
+ result[targetIndex + 1] = data[sourceIndex + 1];
8664
+ result[targetIndex + 2] = data[sourceIndex + 2];
8665
+ result[targetIndex + 3] = data[sourceIndex + 3];
8666
+ }
8667
+ else {
8668
+ result[targetIndex + 3] = 0;
8669
+ }
8670
+ }
8671
+ }
8672
+ return new ImageData(result, width, height);
8673
+ }
8674
+ applySwirlDistortion(imageData, strength, time) {
8675
+ const { data, width, height } = imageData;
8676
+ const result = new Uint8ClampedArray(data.length);
8677
+ const centerX = width / 2;
8678
+ const centerY = height / 2;
8679
+ for (let y = 0; y < height; y++) {
8680
+ for (let x = 0; x < width; x++) {
8681
+ const dx = x - centerX;
8682
+ const dy = y - centerY;
8683
+ const distance = Math.sqrt(dx * dx + dy * dy);
8684
+ const originalAngle = Math.atan2(dy, dx);
8685
+ const rotationAngle = distance * strength * time * 0.02;
8686
+ const finalAngle = originalAngle + rotationAngle;
8687
+ const sourceX = Math.round(centerX + distance * Math.cos(finalAngle));
8688
+ const sourceY = Math.round(centerY + distance * Math.sin(finalAngle));
8689
+ const targetIndex = (y * width + x) * 4;
8690
+ if (sourceX >= 0 && sourceX < width && sourceY >= 0 && sourceY < height) {
8691
+ const sourceIndex = (sourceY * width + sourceX) * 4;
8692
+ result[targetIndex] = data[sourceIndex];
8693
+ result[targetIndex + 1] = data[sourceIndex + 1];
8694
+ result[targetIndex + 2] = data[sourceIndex + 2];
8695
+ result[targetIndex + 3] = data[sourceIndex + 3];
8696
+ }
8697
+ else {
8698
+ result[targetIndex + 3] = 0;
8699
+ }
8700
+ }
8701
+ }
8702
+ return new ImageData(result, width, height);
8703
+ }
8704
+ afterStageRender(stage, canvas) {
8705
+ if (this.distortionConfig.strength <= 0) {
8706
+ return canvas;
8707
+ }
8708
+ return super.afterStageRender(stage, canvas);
8709
+ }
8710
+ }
8711
+
8712
+ class Particle extends HybridEffectBase {
8713
+ constructor(from, to, duration, easing, params) {
8714
+ var _a, _b, _c, _d, _e;
8715
+ super(from, to, duration, easing, params);
8716
+ this.particles = [];
8717
+ this.positionBuffer = null;
8718
+ this.colorBuffer = null;
8719
+ this.particleConfig = {
8720
+ effectType: ((_a = params === null || params === void 0 ? void 0 : params.options) === null || _a === void 0 ? void 0 : _a.effectType) || 'gravity',
8721
+ count: ((_b = params === null || params === void 0 ? void 0 : params.options) === null || _b === void 0 ? void 0 : _b.count) || 4000,
8722
+ size: ((_c = params === null || params === void 0 ? void 0 : params.options) === null || _c === void 0 ? void 0 : _c.size) || 20,
8723
+ strength: ((_d = params === null || params === void 0 ? void 0 : params.options) === null || _d === void 0 ? void 0 : _d.strength) || 1.5,
8724
+ useWebGL: ((_e = params === null || params === void 0 ? void 0 : params.options) === null || _e === void 0 ? void 0 : _e.useWebGL) !== undefined ? params.options.useWebGL : true
8725
+ };
8726
+ }
8727
+ getShaderSources() {
8728
+ const vertexShader = `
8729
+ attribute vec2 a_position;
8730
+ attribute vec4 a_color;
8731
+ attribute float a_size;
8732
+
8733
+ uniform vec2 u_resolution;
8734
+ uniform float u_time;
8735
+ uniform float u_forceStrength;
8736
+ uniform int u_effectType;
8737
+
8738
+ varying vec4 v_color;
8739
+
8740
+ void main() {
8741
+ // 将像素坐标转换为剪辑空间坐标
8742
+ vec2 clipSpace = ((a_position / u_resolution) * 2.0) - 1.0;
8743
+ clipSpace.y = -clipSpace.y; // 翻转Y轴
8744
+
8745
+ gl_Position = vec4(clipSpace, 0.0, 1.0);
8746
+ gl_PointSize = a_size;
8747
+ v_color = a_color;
8748
+ }
8749
+ `;
8750
+ const fragmentShader = `
8751
+ precision mediump float;
8752
+ varying vec4 v_color;
8753
+
8754
+ void main() {
8755
+ // 创建圆形粒子
8756
+ vec2 coord = gl_PointCoord - vec2(0.5);
8757
+ float distance = length(coord);
8758
+
8759
+ if (distance > 0.5) {
8760
+ discard;
8761
+ }
8762
+
8763
+ // 保持原始颜色,只调整透明度渐变
8764
+ gl_FragColor = vec4(v_color.rgb, v_color.a);
8765
+ }
8766
+ `;
8767
+ return { vertex: vertexShader, fragment: fragmentShader };
8768
+ }
8769
+ applyWebGLEffect(canvas) {
8770
+ if (!this.gl || !this.program || !this.webglCanvas) {
8771
+ return null;
8772
+ }
8773
+ this.setupWebGLState(canvas);
8774
+ if (this.particles.length === 0) {
8775
+ this.extractParticles(canvas);
8776
+ }
8777
+ this.updateParticles(canvas);
8778
+ const gl = this.gl;
8779
+ gl.enable(gl.BLEND);
8780
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
8781
+ gl.useProgram(this.program);
8782
+ this.prepareAndDrawParticles(gl);
8783
+ return this.webglCanvas;
8784
+ }
8785
+ applyCanvas2DEffect(canvas) {
8786
+ const output = this.createOutputCanvas(canvas);
8787
+ if (!output) {
8788
+ return null;
8789
+ }
8790
+ const { canvas: outputCanvas, ctx } = output;
8791
+ const progress = this.currentAnimationRatio;
8792
+ switch (this.particleConfig.effectType) {
8793
+ case 'explode':
8794
+ this.applyCanvas2DExplode(ctx, canvas, progress);
8795
+ break;
8796
+ case 'gravity':
8797
+ this.applyCanvas2DGravity(ctx, canvas, progress);
8798
+ break;
8799
+ case 'vortex':
8800
+ this.applyCanvas2DVortex(ctx, canvas, progress);
8801
+ break;
8802
+ default:
8803
+ ctx.globalAlpha = Math.max(0, 1 - progress);
8804
+ ctx.drawImage(canvas, 0, 0);
8805
+ }
8806
+ return outputCanvas;
8807
+ }
8808
+ extractParticles(canvas) {
8809
+ const tempCanvas = ImageProcessUtils.createTempCanvas(canvas.width, canvas.height, 1);
8810
+ const tempCtx = tempCanvas.getContext('2d');
8811
+ if (!tempCtx) {
8812
+ return;
8813
+ }
8814
+ tempCtx.drawImage(canvas, 0, 0, tempCanvas.width, tempCanvas.height);
8815
+ const imageData = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height);
8816
+ const data = imageData.data;
8817
+ this.particles = [];
8818
+ const step = Math.max(1, Math.floor(Math.sqrt((tempCanvas.width * tempCanvas.height) / (this.particleConfig.count * 1.5))));
8819
+ for (let y = 0; y < tempCanvas.height; y += step) {
8820
+ for (let x = 0; x < tempCanvas.width; x += step) {
8821
+ const index = (y * tempCanvas.width + x) * 4;
8822
+ const r = data[index];
8823
+ const g = data[index + 1];
8824
+ const b = data[index + 2];
8825
+ const a = data[index + 3];
8826
+ if (a > 5) {
8827
+ const realX = (x / tempCanvas.width) * canvas.width;
8828
+ const realY = (y / tempCanvas.height) * canvas.height;
8829
+ const particle = {
8830
+ x: realX,
8831
+ y: realY,
8832
+ originX: realX,
8833
+ originY: realY,
8834
+ vx: 0,
8835
+ vy: 0,
8836
+ r: r / 255,
8837
+ g: g / 255,
8838
+ b: b / 255,
8839
+ a: Math.max(0.6, a / 255),
8840
+ life: 1.0,
8841
+ size: this.particleConfig.size * (1 + Math.random() * 0.5)
8842
+ };
8843
+ this.particles.push(particle);
8844
+ }
8845
+ }
8846
+ }
8847
+ }
8848
+ updateParticles(canvas) {
8849
+ const centerX = canvas.width / 2;
8850
+ const centerY = canvas.height / 2;
8851
+ const progress = this.currentAnimationRatio;
8852
+ const duration = this.getDurationFromParent();
8853
+ const isShortAnimation = duration < 2000;
8854
+ const timeMultiplier = isShortAnimation ? Math.max(1.5, 3000 / duration) : 1.0;
8855
+ const intensityBoost = isShortAnimation ? Math.min(2.0, 2000 / duration) : 1.0;
8856
+ this.particles.forEach(particle => {
8857
+ const dx = particle.x - centerX;
8858
+ const dy = particle.y - centerY;
8859
+ const distance = Math.sqrt(dx * dx + dy * dy);
8860
+ const angle = Math.atan2(dy, dx);
8861
+ this.applyParticleForces(particle, angle, distance, progress, intensityBoost, canvas);
8862
+ this.updateParticleProperties(particle, progress, isShortAnimation, timeMultiplier, intensityBoost);
8863
+ });
8864
+ }
8865
+ applyParticleForces(particle, angle, distance, progress, intensityBoost, canvas) {
8866
+ const time = this.getAnimationTime();
8867
+ switch (this.particleConfig.effectType) {
8868
+ case 'explode':
8869
+ const explodeIntensity = progress * this.particleConfig.strength * intensityBoost * 5;
8870
+ particle.vx += Math.cos(angle) * explodeIntensity;
8871
+ particle.vy += Math.sin(angle) * explodeIntensity;
8872
+ break;
8873
+ case 'gravity':
8874
+ this.applyGravityEffect(particle, progress, intensityBoost, canvas, time);
8875
+ break;
8876
+ case 'vortex':
8877
+ this.applyVortexEffect(particle, progress, intensityBoost, canvas, angle, distance);
8878
+ break;
8879
+ }
8880
+ }
8881
+ applyGravityEffect(particle, progress, intensityBoost, canvas, time) {
8882
+ const gravityThreshold = ((particle.originX + particle.originY * 0.7) / (canvas.width + canvas.height)) * 0.8;
8883
+ if (progress > gravityThreshold) {
8884
+ const gravityProgress = (progress - gravityThreshold) / (1 - gravityThreshold);
8885
+ const gravityForce = this.particleConfig.strength * gravityProgress * gravityProgress * 12 * intensityBoost;
8886
+ particle.vy += gravityForce;
8887
+ const turbulence = Math.sin(time * 3 + particle.originX * 0.02) * Math.cos(time * 2 + particle.originY * 0.015);
8888
+ particle.vx += turbulence * this.particleConfig.strength * 2 * intensityBoost;
8889
+ }
8890
+ }
8891
+ applyVortexEffect(particle, progress, intensityBoost, canvas, angle, distance) {
8892
+ const centerX = canvas.width / 2;
8893
+ const centerY = canvas.height / 2;
8894
+ const spiralAngle = angle + progress * Math.PI * 0.8;
8895
+ const targetRadius = distance + progress * Math.max(canvas.width, canvas.height) * 0.7 * 1.8;
8896
+ const targetX = centerX + Math.cos(spiralAngle) * targetRadius;
8897
+ const targetY = centerY + Math.sin(spiralAngle) * targetRadius;
8898
+ const baseForce = progress * this.particleConfig.strength * 0.08 * intensityBoost;
8899
+ particle.vx += (targetX - particle.x) * baseForce;
8900
+ particle.vy += (targetY - particle.y) * baseForce;
8901
+ }
8902
+ updateParticleProperties(particle, progress, isShortAnimation, timeMultiplier, intensityBoost) {
8903
+ const dragCoeff = isShortAnimation ? 0.99 : 0.98;
8904
+ particle.vx *= dragCoeff;
8905
+ particle.vy *= dragCoeff;
8906
+ particle.x += particle.vx;
8907
+ particle.y += particle.vy;
8908
+ if (isShortAnimation) {
8909
+ const lifeDecayRate = Math.max(0.1, 0.5 / timeMultiplier);
8910
+ particle.life = Math.max(0, 1 - progress * lifeDecayRate);
8911
+ particle.a = Math.max(0.2, particle.life * Math.min(1, particle.a * 1.2));
8912
+ particle.size = Math.max(this.particleConfig.size * 0.7, this.particleConfig.size * (0.5 + particle.life * 0.5));
8913
+ }
8914
+ else {
8915
+ particle.life = Math.max(0, 1 - progress * 0.2);
8916
+ particle.a = Math.max(0.1, particle.life * Math.min(1, particle.a * 1.5));
8917
+ particle.size = Math.max(this.particleConfig.size * 0.5, this.particleConfig.size * (0.3 + particle.life * 0.7));
8918
+ }
8919
+ }
8920
+ prepareAndDrawParticles(gl) {
8921
+ const positions = new Float32Array(this.particles.length * 2);
8922
+ const colors = new Float32Array(this.particles.length * 4);
8923
+ const sizes = new Float32Array(this.particles.length);
8924
+ this.particles.forEach((particle, i) => {
8925
+ positions[i * 2] = particle.x;
8926
+ positions[i * 2 + 1] = particle.y;
8927
+ colors[i * 4] = particle.r;
8928
+ colors[i * 4 + 1] = particle.g;
8929
+ colors[i * 4 + 2] = particle.b;
8930
+ colors[i * 4 + 3] = Math.max(0.1, particle.a);
8931
+ sizes[i] = Math.max(6, particle.size * 1.5);
8932
+ });
8933
+ this.updateParticleBuffers(gl, positions, colors, sizes);
8934
+ this.setParticleUniforms(gl);
8935
+ gl.drawArrays(gl.POINTS, 0, this.particles.length);
8936
+ this.cleanupTempBuffers(gl);
8937
+ }
8938
+ updateParticleBuffers(gl, positions, colors, sizes) {
8939
+ if (!this.positionBuffer) {
8940
+ this.positionBuffer = gl.createBuffer();
8941
+ }
8942
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer);
8943
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.DYNAMIC_DRAW);
8944
+ const positionLocation = gl.getAttribLocation(this.program, 'a_position');
8945
+ gl.enableVertexAttribArray(positionLocation);
8946
+ gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
8947
+ if (!this.colorBuffer) {
8948
+ this.colorBuffer = gl.createBuffer();
8949
+ }
8950
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer);
8951
+ gl.bufferData(gl.ARRAY_BUFFER, colors, gl.DYNAMIC_DRAW);
8952
+ const colorLocation = gl.getAttribLocation(this.program, 'a_color');
8953
+ gl.enableVertexAttribArray(colorLocation);
8954
+ gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, false, 0, 0);
8955
+ const sizeBuffer = gl.createBuffer();
8956
+ gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer);
8957
+ gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.DYNAMIC_DRAW);
8958
+ const sizeLocation = gl.getAttribLocation(this.program, 'a_size');
8959
+ gl.enableVertexAttribArray(sizeLocation);
8960
+ gl.vertexAttribPointer(sizeLocation, 1, gl.FLOAT, false, 0, 0);
8961
+ this._tempSizeBuffer = sizeBuffer;
8962
+ }
8963
+ setParticleUniforms(gl) {
8964
+ const resolutionLocation = gl.getUniformLocation(this.program, 'u_resolution');
8965
+ const timeLocation = gl.getUniformLocation(this.program, 'u_time');
8966
+ const forceStrengthLocation = gl.getUniformLocation(this.program, 'u_forceStrength');
8967
+ const effectTypeLocation = gl.getUniformLocation(this.program, 'u_effectType');
8968
+ gl.uniform2f(resolutionLocation, this.webglCanvas.width, this.webglCanvas.height);
8969
+ gl.uniform1f(timeLocation, this.getAnimationTime());
8970
+ gl.uniform1f(forceStrengthLocation, this.particleConfig.strength);
8971
+ const effectTypeMap = {
8972
+ explode: 0,
8973
+ vortex: 1,
8974
+ gravity: 2
8975
+ };
8976
+ gl.uniform1i(effectTypeLocation, effectTypeMap[this.particleConfig.effectType] || 0);
8977
+ }
8978
+ cleanupTempBuffers(gl) {
8979
+ const tempSizeBuffer = this._tempSizeBuffer;
8980
+ if (tempSizeBuffer) {
8981
+ gl.deleteBuffer(tempSizeBuffer);
8982
+ delete this._tempSizeBuffer;
8983
+ }
8984
+ }
8985
+ applyCanvas2DExplode(ctx, canvas, progress) {
8986
+ const centerX = canvas.width / 2;
8987
+ const centerY = canvas.height / 2;
8988
+ ctx.save();
8989
+ ctx.globalAlpha = Math.max(0, 1 - progress);
8990
+ ctx.translate(centerX, centerY);
8991
+ const scale = 1 + progress * 0.5;
8992
+ ctx.scale(scale, scale);
8993
+ ctx.translate(-centerX, -centerY);
8994
+ ctx.drawImage(canvas, 0, 0);
8995
+ ctx.restore();
8996
+ }
8997
+ applyCanvas2DGravity(ctx, canvas, progress) {
8998
+ ctx.save();
8999
+ ctx.globalAlpha = Math.max(0, 1 - progress);
9000
+ const offsetY = progress * canvas.height * 0.3;
9001
+ ctx.drawImage(canvas, 0, offsetY);
9002
+ ctx.restore();
9003
+ }
9004
+ applyCanvas2DVortex(ctx, canvas, progress) {
9005
+ const centerX = canvas.width / 2;
9006
+ const centerY = canvas.height / 2;
9007
+ ctx.save();
9008
+ ctx.globalAlpha = Math.max(0, 1 - progress);
9009
+ ctx.translate(centerX, centerY);
9010
+ ctx.rotate(progress * Math.PI * 2);
9011
+ ctx.translate(-centerX, -centerY);
9012
+ ctx.drawImage(canvas, 0, 0);
9013
+ ctx.restore();
9014
+ }
9015
+ }
9016
+
9017
+ class Glitch extends Canvas2DEffectBase {
9018
+ constructor(from, to, duration, easing, params) {
9019
+ var _a, _b;
9020
+ super(from, to, duration, easing, params);
9021
+ this.glitchConfig = {
9022
+ effectType: ((_a = params === null || params === void 0 ? void 0 : params.options) === null || _a === void 0 ? void 0 : _a.effectType) || 'rgb-shift',
9023
+ intensity: ((_b = params === null || params === void 0 ? void 0 : params.options) === null || _b === void 0 ? void 0 : _b.intensity) !== undefined ? params.options.intensity : 0.5
9024
+ };
9025
+ }
9026
+ applyCanvas2DEffect(canvas) {
9027
+ if (this.glitchConfig.intensity <= 0) {
9028
+ const outputCanvas = this.createOutputCanvas(canvas);
9029
+ return outputCanvas ? outputCanvas.canvas : null;
9030
+ }
9031
+ try {
9032
+ switch (this.glitchConfig.effectType) {
9033
+ case 'rgb-shift':
9034
+ return this.applyRGBShiftGlitch(canvas);
9035
+ case 'digital-distortion':
9036
+ return this.applyDigitalDistortionGlitch(canvas);
9037
+ case 'scan-lines':
9038
+ return this.applyScanLineGlitch(canvas);
9039
+ case 'data-corruption':
9040
+ return this.applyDataCorruptionGlitch(canvas);
9041
+ default:
9042
+ return this.applyRGBShiftGlitch(canvas);
9043
+ }
9044
+ }
9045
+ catch (error) {
9046
+ console.warn('Glitch effect failed:', error);
9047
+ return null;
9048
+ }
9049
+ }
9050
+ applyRGBShiftGlitch(canvas) {
9051
+ const outputCanvas = this.createOutputCanvas(canvas);
9052
+ if (!outputCanvas) {
9053
+ return null;
9054
+ }
9055
+ const { ctx } = outputCanvas;
9056
+ try {
9057
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
9058
+ const dynamicIntensity = ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime());
9059
+ const maxOffset = Math.floor(dynamicIntensity * 20);
9060
+ const redOffset = this.generateRandomOffset(maxOffset);
9061
+ const greenOffset = this.generateRandomOffset(maxOffset, 0.3);
9062
+ const blueOffset = this.generateRandomOffset(-maxOffset);
9063
+ const tempCanvas = ImageProcessUtils.createTempCanvas(canvas.width, canvas.height);
9064
+ const tempCtx = tempCanvas.getContext('2d');
9065
+ tempCtx.drawImage(canvas, 0, 0);
9066
+ const originalImageData = tempCtx.getImageData(0, 0, canvas.width, canvas.height);
9067
+ const redChannelData = ImageProcessUtils.extractChannel(originalImageData, 0);
9068
+ const greenChannelData = ImageProcessUtils.extractChannel(originalImageData, 1);
9069
+ const blueChannelData = ImageProcessUtils.extractChannel(originalImageData, 2);
9070
+ ctx.globalCompositeOperation = 'screen';
9071
+ tempCtx.clearRect(0, 0, canvas.width, canvas.height);
9072
+ tempCtx.putImageData(redChannelData, 0, 0);
9073
+ ctx.drawImage(tempCanvas, redOffset.x, redOffset.y);
9074
+ tempCtx.clearRect(0, 0, canvas.width, canvas.height);
9075
+ tempCtx.putImageData(greenChannelData, 0, 0);
9076
+ ctx.drawImage(tempCanvas, greenOffset.x, greenOffset.y);
9077
+ tempCtx.clearRect(0, 0, canvas.width, canvas.height);
9078
+ tempCtx.putImageData(blueChannelData, 0, 0);
9079
+ ctx.drawImage(tempCanvas, blueOffset.x, blueOffset.y);
9080
+ ctx.globalCompositeOperation = 'source-over';
9081
+ return outputCanvas.canvas;
9082
+ }
9083
+ catch (error) {
9084
+ console.warn('RGB shift glitch failed:', error);
9085
+ return null;
9086
+ }
9087
+ }
9088
+ applyDigitalDistortionGlitch(canvas) {
9089
+ const outputCanvas = this.createOutputCanvas(canvas);
9090
+ if (!outputCanvas) {
9091
+ return null;
9092
+ }
9093
+ const { ctx } = outputCanvas;
9094
+ try {
9095
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
9096
+ const dynamicIntensity = ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime());
9097
+ const distortedImageData = this.processDigitalDistortion(imageData, dynamicIntensity);
9098
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
9099
+ ctx.putImageData(distortedImageData, 0, 0);
9100
+ return outputCanvas.canvas;
9101
+ }
9102
+ catch (error) {
9103
+ console.warn('Digital distortion glitch failed:', error);
9104
+ return null;
9105
+ }
9106
+ }
9107
+ applyScanLineGlitch(canvas) {
9108
+ const outputCanvas = this.createOutputCanvas(canvas);
9109
+ if (!outputCanvas) {
9110
+ return null;
9111
+ }
9112
+ const { ctx } = outputCanvas;
9113
+ try {
9114
+ const dynamicIntensity = ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime());
9115
+ const lineSpacing = Math.max(2, Math.floor(10 - dynamicIntensity * 8));
9116
+ ctx.globalCompositeOperation = 'multiply';
9117
+ for (let y = 0; y < canvas.height; y += lineSpacing) {
9118
+ if (Math.random() < dynamicIntensity) {
9119
+ const opacity = 0.1 + dynamicIntensity * 0.4;
9120
+ ctx.fillStyle = `rgba(0, 0, 0, ${opacity})`;
9121
+ ctx.fillRect(0, y, canvas.width, 1);
9122
+ }
9123
+ }
9124
+ ctx.globalCompositeOperation = 'screen';
9125
+ const brightLineCount = Math.floor(dynamicIntensity * 20);
9126
+ for (let i = 0; i < brightLineCount; i++) {
9127
+ const y = Math.random() * canvas.height;
9128
+ const opacity = dynamicIntensity * 0.3;
9129
+ ctx.fillStyle = `rgba(255, 255, 255, ${opacity})`;
9130
+ ctx.fillRect(0, Math.floor(y), canvas.width, 1);
9131
+ }
9132
+ ctx.globalCompositeOperation = 'source-over';
9133
+ return outputCanvas.canvas;
9134
+ }
9135
+ catch (error) {
9136
+ console.warn('Scan line glitch failed:', error);
9137
+ return null;
9138
+ }
9139
+ }
9140
+ applyDataCorruptionGlitch(canvas) {
9141
+ const outputCanvas = this.createOutputCanvas(canvas);
9142
+ if (!outputCanvas) {
9143
+ return null;
9144
+ }
9145
+ const { ctx } = outputCanvas;
9146
+ try {
9147
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
9148
+ const dynamicIntensity = ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime());
9149
+ const corruptedImageData = this.processDataCorruption(imageData, dynamicIntensity);
9150
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
9151
+ ctx.putImageData(corruptedImageData, 0, 0);
9152
+ return outputCanvas.canvas;
9153
+ }
9154
+ catch (error) {
9155
+ console.warn('Data corruption glitch failed:', error);
9156
+ return null;
9157
+ }
9158
+ }
9159
+ generateRandomOffset(maxOffset, scale = 1) {
9160
+ return {
9161
+ x: (Math.random() - 0.5) * maxOffset,
9162
+ y: (Math.random() - 0.5) * maxOffset * scale
9163
+ };
9164
+ }
9165
+ processDigitalDistortion(imageData, intensity) {
9166
+ const { data, width, height } = imageData;
9167
+ const result = new Uint8ClampedArray(data);
9168
+ const sliceCount = Math.floor(intensity * 20) + 5;
9169
+ const sliceHeight = Math.floor(height / sliceCount);
9170
+ for (let i = 0; i < sliceCount; i++) {
9171
+ if (Math.random() < intensity) {
9172
+ const y = i * sliceHeight;
9173
+ const sliceEnd = Math.min(y + sliceHeight, height);
9174
+ const offset = Math.floor((Math.random() - 0.5) * width * intensity * 0.1);
9175
+ this.shiftSliceHorizontal(result, width, height, y, sliceEnd, offset);
9176
+ }
9177
+ }
9178
+ const noiseIntensity = intensity * 0.3;
9179
+ for (let i = 0; i < data.length; i += 4) {
9180
+ if (Math.random() < noiseIntensity) {
9181
+ result[i] = Math.random() * 255;
9182
+ result[i + 1] = Math.random() * 255;
9183
+ result[i + 2] = Math.random() * 255;
9184
+ }
9185
+ }
9186
+ return new ImageData(result, width, height);
9187
+ }
9188
+ shiftSliceHorizontal(data, width, height, startY, endY, offset) {
9189
+ const tempRow = new Uint8ClampedArray(width * 4);
9190
+ for (let y = startY; y < endY; y++) {
9191
+ const rowStart = y * width * 4;
9192
+ for (let x = 0; x < width * 4; x++) {
9193
+ tempRow[x] = data[rowStart + x];
9194
+ }
9195
+ for (let x = 0; x < width; x++) {
9196
+ const sourceX = (x - offset + width) % width;
9197
+ const targetIndex = rowStart + x * 4;
9198
+ const sourceIndex = sourceX * 4;
9199
+ data[targetIndex] = tempRow[sourceIndex];
9200
+ data[targetIndex + 1] = tempRow[sourceIndex + 1];
9201
+ data[targetIndex + 2] = tempRow[sourceIndex + 2];
9202
+ data[targetIndex + 3] = tempRow[sourceIndex + 3];
9203
+ }
9204
+ }
9205
+ }
9206
+ processDataCorruption(imageData, intensity) {
9207
+ const { data, width, height } = imageData;
9208
+ const result = new Uint8ClampedArray(data);
9209
+ const stripeCount = Math.floor(intensity * 15) + 5;
9210
+ for (let i = 0; i < stripeCount; i++) {
9211
+ if (Math.random() < intensity) {
9212
+ const x = Math.floor(Math.random() * width);
9213
+ const stripeWidth = Math.floor(Math.random() * 5) + 1;
9214
+ const color = Math.random() < 0.5 ? 0 : 255;
9215
+ for (let y = 0; y < height; y++) {
9216
+ for (let dx = 0; dx < stripeWidth && x + dx < width; dx++) {
9217
+ const index = (y * width + x + dx) * 4;
9218
+ result[index] = color;
9219
+ result[index + 1] = color;
9220
+ result[index + 2] = color;
9221
+ }
9222
+ }
9223
+ }
9224
+ }
9225
+ const corruptionCount = Math.floor(intensity * 20);
9226
+ for (let i = 0; i < corruptionCount; i++) {
9227
+ const blockX = Math.floor(Math.random() * width);
9228
+ const blockY = Math.floor(Math.random() * height);
9229
+ const blockW = Math.floor(Math.random() * 20) + 5;
9230
+ const blockH = Math.floor(Math.random() * 10) + 2;
9231
+ this.corruptBlock(result, width, height, blockX, blockY, blockW, blockH);
9232
+ }
9233
+ return new ImageData(result, width, height);
9234
+ }
9235
+ corruptBlock(data, width, height, x, y, w, h) {
9236
+ for (let dy = 0; dy < h && y + dy < height; dy++) {
9237
+ for (let dx = 0; dx < w && x + dx < width; dx++) {
9238
+ const index = ((y + dy) * width + (x + dx)) * 4;
9239
+ if (Math.random() < 0.7) {
9240
+ data[index] = Math.random() * 255;
9241
+ data[index + 1] = Math.random() * 255;
9242
+ data[index + 2] = Math.random() * 255;
9243
+ }
9244
+ }
9245
+ }
9246
+ }
9247
+ }
9248
+
9249
+ class GaussianBlur extends AStageAnimate {
9250
+ constructor(from, to, duration, easing, params) {
9251
+ var _a, _b;
9252
+ super(from, to, duration, easing, params);
9253
+ this.blurConfig = {
9254
+ blurRadius: ((_a = params === null || params === void 0 ? void 0 : params.options) === null || _a === void 0 ? void 0 : _a.blurRadius) || 8,
9255
+ useOptimizedBlur: ((_b = params === null || params === void 0 ? void 0 : params.options) === null || _b === void 0 ? void 0 : _b.useOptimizedBlur) !== undefined ? params.options.useOptimizedBlur : true
9256
+ };
9257
+ }
9258
+ applyCSSBlur(canvas, radius) {
9259
+ const c = vglobal.createCanvas({
9260
+ width: canvas.width,
9261
+ height: canvas.height,
9262
+ dpr: vglobal.devicePixelRatio
9263
+ });
9264
+ const ctx = c.getContext('2d');
9265
+ if (!ctx) {
9266
+ return canvas;
9267
+ }
9268
+ ctx.filter = `blur(${radius}px)`;
9269
+ ctx.drawImage(canvas, 0, 0);
9270
+ ctx.filter = 'none';
9271
+ return c;
9272
+ }
9273
+ applyDownsampleBlur(imageData, radius) {
9274
+ const { width, height } = imageData;
9275
+ const downsample = Math.max(1, Math.floor(radius / 2));
9276
+ const smallWidth = Math.floor(width / downsample);
9277
+ const smallHeight = Math.floor(height / downsample);
9278
+ const tempCanvas = vglobal.createCanvas({
9279
+ width: smallWidth,
9280
+ height: smallHeight,
9281
+ dpr: 1
9282
+ });
9283
+ const tempCtx = tempCanvas.getContext('2d');
9284
+ if (!tempCtx) {
9285
+ return imageData;
9286
+ }
9287
+ const originalCanvas = vglobal.createCanvas({
9288
+ width: width,
9289
+ height: height,
9290
+ dpr: 1
9291
+ });
9292
+ const originalCtx = originalCanvas.getContext('2d');
9293
+ if (!originalCtx) {
9294
+ return imageData;
9295
+ }
9296
+ originalCtx.putImageData(imageData, 0, 0);
9297
+ tempCtx.drawImage(originalCanvas, 0, 0, smallWidth, smallHeight);
9298
+ tempCtx.filter = `blur(${radius / downsample}px)`;
9299
+ tempCtx.drawImage(tempCanvas, 0, 0);
9300
+ tempCtx.filter = 'none';
9301
+ originalCtx.clearRect(0, 0, width, height);
9302
+ originalCtx.drawImage(tempCanvas, 0, 0, width, height);
9303
+ return originalCtx.getImageData(0, 0, width, height);
9304
+ }
9305
+ afterStageRender(stage, canvas) {
9306
+ if (this.blurConfig.blurRadius <= 0) {
9307
+ return canvas;
9308
+ }
9309
+ let result;
9310
+ if (this.blurConfig.useOptimizedBlur) {
9311
+ result = this.applyCSSBlur(canvas, this.blurConfig.blurRadius);
9312
+ }
9313
+ else {
9314
+ const c = vglobal.createCanvas({
9315
+ width: canvas.width,
9316
+ height: canvas.height,
9317
+ dpr: vglobal.devicePixelRatio
9318
+ });
9319
+ const ctx = c.getContext('2d');
9320
+ if (!ctx) {
9321
+ return false;
9322
+ }
9323
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
9324
+ ctx.drawImage(canvas, 0, 0);
9325
+ const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
9326
+ const blurredImageData = this.applyDownsampleBlur(imageData, this.blurConfig.blurRadius);
9327
+ ctx.putImageData(blurredImageData, 0, 0);
9328
+ result = c;
9329
+ }
9330
+ const ctx = result.getContext('2d');
9331
+ if (ctx) {
9332
+ ctx.globalCompositeOperation = 'overlay';
9333
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.1)';
9334
+ ctx.fillRect(0, 0, result.width, result.height);
9335
+ ctx.globalCompositeOperation = 'source-over';
9336
+ }
9337
+ return result;
9338
+ }
9339
+ }
9340
+
9341
+ class Pixelation extends DisappearAnimateBase {
9342
+ constructor(from, to, duration, easing, params) {
9343
+ var _a, _b;
9344
+ super(from, to, duration, easing, params);
9345
+ this.pixelationConfig = {
9346
+ maxPixelSize: ((_a = params === null || params === void 0 ? void 0 : params.options) === null || _a === void 0 ? void 0 : _a.maxPixelSize) || 20,
9347
+ method: ((_b = params === null || params === void 0 ? void 0 : params.options) === null || _b === void 0 ? void 0 : _b.method) || 'out'
9348
+ };
9349
+ }
9350
+ applyDownsamplePixelation(canvas, pixelSize) {
9351
+ if (pixelSize <= 1) {
9352
+ return canvas;
9353
+ }
9354
+ const { width, height } = canvas;
9355
+ const smallWidth = Math.ceil(width / pixelSize);
9356
+ const smallHeight = Math.ceil(height / pixelSize);
9357
+ const smallCanvas = vglobal.createCanvas({
9358
+ width: smallWidth,
9359
+ height: smallHeight,
9360
+ dpr: 1
9361
+ });
9362
+ const smallCtx = smallCanvas.getContext('2d');
9363
+ if (!smallCtx) {
9364
+ return canvas;
9365
+ }
9366
+ const outputCanvas = vglobal.createCanvas({
9367
+ width: width,
9368
+ height: height,
9369
+ dpr: vglobal.devicePixelRatio
9370
+ });
9371
+ const outputCtx = outputCanvas.getContext('2d');
9372
+ if (!outputCtx) {
9373
+ return canvas;
9374
+ }
9375
+ smallCtx.imageSmoothingEnabled = false;
9376
+ outputCtx.imageSmoothingEnabled = false;
9377
+ smallCtx.drawImage(canvas, 0, 0, smallWidth, smallHeight);
9378
+ outputCtx.drawImage(smallCanvas, 0, 0, width, height);
9379
+ return outputCanvas;
9380
+ }
9381
+ updateAnimationProgress() {
9382
+ if (this.pixelationConfig.method === 'in') {
9383
+ const currentPixelSize = this.pixelationConfig.maxPixelSize - this.currentAnimationRatio * (this.pixelationConfig.maxPixelSize - 1);
9384
+ return currentPixelSize;
9385
+ }
9386
+ const currentPixelSize = 1 + this.currentAnimationRatio * (this.pixelationConfig.maxPixelSize - 1);
9387
+ return currentPixelSize;
9388
+ }
9389
+ afterStageRender(stage, canvas) {
9390
+ const currentPixelSize = this.updateAnimationProgress();
9391
+ if (currentPixelSize <= 1) {
9392
+ return canvas;
9393
+ }
9394
+ const result = this.applyDownsamplePixelation(canvas, currentPixelSize);
9395
+ return result;
9396
+ }
9397
+ }
9398
+
7159
9399
  const registerCustomAnimate = () => {
7160
9400
  AnimateExecutor.registerBuiltInAnimate('increaseCount', IncreaseCount);
7161
9401
  AnimateExecutor.registerBuiltInAnimate('fromTo', FromTo);
@@ -7211,6 +9451,13 @@ const registerCustomAnimate = () => {
7211
9451
  AnimateExecutor.registerBuiltInAnimate('pulse', PulseAnimate);
7212
9452
  AnimateExecutor.registerBuiltInAnimate('MotionPath', MotionPath);
7213
9453
  AnimateExecutor.registerBuiltInAnimate('streamLight', StreamLight);
9454
+ AnimateExecutor.registerBuiltInAnimate('dissolve', Dissolve);
9455
+ AnimateExecutor.registerBuiltInAnimate('grayscale', Grayscale);
9456
+ AnimateExecutor.registerBuiltInAnimate('distortion', Distortion);
9457
+ AnimateExecutor.registerBuiltInAnimate('particle', Particle);
9458
+ AnimateExecutor.registerBuiltInAnimate('glitch', Glitch);
9459
+ AnimateExecutor.registerBuiltInAnimate('gaussianBlur', GaussianBlur);
9460
+ AnimateExecutor.registerBuiltInAnimate('pixelation', Pixelation);
7214
9461
  };
7215
9462
 
7216
- export { AComponentAnimate, ACustomAnimate, AStageAnimate, Animate, AnimateExecutor, Step as AnimateStep, AnimationStateManager, AnimationStateStore, AnimationStates, AnimationTransitionRegistry, ClipAngleAnimate, ClipDirectionAnimate, ClipGraphicAnimate, ClipIn, ClipOut, ClipRadiusAnimate, ComponentAnimator, DefaultTicker, DefaultTimeline, Easing, FadeIn, FadeOut, FromTo, GraphicStateExtension, GroupFadeIn, GroupFadeOut, GrowAngleIn, GrowAngleOut, GrowCenterIn, GrowCenterOut, GrowHeightIn, GrowHeightOut, GrowIn, GrowOut, GrowPointsIn, GrowPointsOut, GrowPointsXIn, GrowPointsXOut, GrowPointsYIn, GrowPointsYOut, GrowRadiusIn, GrowRadiusOut, GrowWidthIn, GrowWidthOut, IncreaseCount, InputRichText, InputText, LabelItemAppear, LabelItemDisappear, ManualTicker, MorphingPath, MotionPath, MoveIn, MoveOut, MoveRotateIn, MoveRotateOut, MoveScaleIn, MoveScaleOut, MultiToOneMorphingPath, OutputRichText, PoptipAppear, PoptipDisappear, PulseAnimate, RotateBySphereAnimate, RotateIn, RotateOut, ScaleIn, ScaleOut, SlideIn, SlideOut, SlideOutRichText, SlideRichText, SpinIn, SpinOut, State, StreamLight, StrokeIn, StrokeOut, TagPointsUpdate, Update, createComponentAnimator, generatorPathEasingFunc, morphPath, multiToOneMorph, oneToMultiMorph, registerAnimate, registerCustomAnimate, transitionRegistry };
9463
+ export { AComponentAnimate, ACustomAnimate, AStageAnimate, Animate, AnimateExecutor, Step as AnimateStep, AnimationStateManager, AnimationStateStore, AnimationStates, AnimationTransitionRegistry, ClipAngleAnimate, ClipDirectionAnimate, ClipGraphicAnimate, ClipIn, ClipOut, ClipRadiusAnimate, ComponentAnimator, DefaultTicker, DefaultTimeline, Dissolve, Distortion, Easing, FadeIn, FadeOut, FromTo, GaussianBlur, Glitch, GraphicStateExtension, Grayscale, GroupFadeIn, GroupFadeOut, GrowAngleIn, GrowAngleOut, GrowCenterIn, GrowCenterOut, GrowHeightIn, GrowHeightOut, GrowIn, GrowOut, GrowPointsIn, GrowPointsOut, GrowPointsXIn, GrowPointsXOut, GrowPointsYIn, GrowPointsYOut, GrowRadiusIn, GrowRadiusOut, GrowWidthIn, GrowWidthOut, IncreaseCount, InputRichText, InputText, LabelItemAppear, LabelItemDisappear, ManualTicker, MorphingPath, MotionPath, MoveIn, MoveOut, MoveRotateIn, MoveRotateOut, MoveScaleIn, MoveScaleOut, MultiToOneMorphingPath, OutputRichText, Particle, Pixelation, PoptipAppear, PoptipDisappear, PulseAnimate, RotateBySphereAnimate, RotateIn, RotateOut, ScaleIn, ScaleOut, SlideIn, SlideOut, SlideOutRichText, SlideRichText, SpinIn, SpinOut, State, StreamLight, StrokeIn, StrokeOut, TagPointsUpdate, Update, createComponentAnimator, generatorPathEasingFunc, morphPath, multiToOneMorph, oneToMultiMorph, registerAnimate, registerCustomAnimate, transitionRegistry };