@visactor/vrender 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.
- package/cjs/index.d.ts +1 -1
- package/cjs/index.js +1 -1
- package/cjs/index.js.map +1 -1
- package/dist/index.es.js +1322 -22
- package/dist/index.js +1329 -21
- package/dist/index.min.js +1 -1
- package/es/index.d.ts +1 -1
- package/es/index.js +1 -1
- package/es/index.js.map +1 -1
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -4615,6 +4615,34 @@
|
|
|
4615
4615
|
}
|
|
4616
4616
|
return c;
|
|
4617
4617
|
}
|
|
4618
|
+
static processColorStops(colorStops) {
|
|
4619
|
+
if (!colorStops || 0 === colorStops.length) return [];
|
|
4620
|
+
if (colorStops.some(item => item.length)) {
|
|
4621
|
+
const stops = colorStops.map(item => ({
|
|
4622
|
+
color: item.value,
|
|
4623
|
+
offset: item.length ? parseFloat(item.length.value) / 100 : -1
|
|
4624
|
+
}));
|
|
4625
|
+
stops[0].offset < 0 && (stops[0].offset = 0), stops[stops.length - 1].offset < 0 && (stops[stops.length - 1].offset = 1);
|
|
4626
|
+
for (let i = 1; i < stops.length - 1; i++) if (stops[i].offset < 0) {
|
|
4627
|
+
const prevWithOffsetIdx = i - 1;
|
|
4628
|
+
let nextWithOffsetIdx = i + 1;
|
|
4629
|
+
for (; nextWithOffsetIdx < stops.length && stops[nextWithOffsetIdx].offset < 0;) nextWithOffsetIdx++;
|
|
4630
|
+
const startOffset = stops[prevWithOffsetIdx].offset,
|
|
4631
|
+
endOffset = stops[nextWithOffsetIdx].offset,
|
|
4632
|
+
unspecCount = nextWithOffsetIdx - prevWithOffsetIdx;
|
|
4633
|
+
for (let j = 1; j < unspecCount; j++) stops[prevWithOffsetIdx + j].offset = startOffset + (endOffset - startOffset) * j / unspecCount;
|
|
4634
|
+
i = nextWithOffsetIdx - 1;
|
|
4635
|
+
}
|
|
4636
|
+
return stops;
|
|
4637
|
+
}
|
|
4638
|
+
return colorStops.map((item, index) => {
|
|
4639
|
+
const offset = colorStops.length > 1 ? index / (colorStops.length - 1) : 0;
|
|
4640
|
+
return {
|
|
4641
|
+
color: item.value,
|
|
4642
|
+
offset: offset
|
|
4643
|
+
};
|
|
4644
|
+
});
|
|
4645
|
+
}
|
|
4618
4646
|
static ParseConic(datum) {
|
|
4619
4647
|
const {
|
|
4620
4648
|
orientation: orientation,
|
|
@@ -4628,10 +4656,7 @@
|
|
|
4628
4656
|
y: .5,
|
|
4629
4657
|
startAngle: sa,
|
|
4630
4658
|
endAngle: sa + pi2,
|
|
4631
|
-
stops:
|
|
4632
|
-
color: item.value,
|
|
4633
|
-
offset: parseFloat(item.length.value) / 100
|
|
4634
|
-
}))
|
|
4659
|
+
stops: GradientParser.processColorStops(colorStops)
|
|
4635
4660
|
};
|
|
4636
4661
|
}
|
|
4637
4662
|
static ParseRadial(datum) {
|
|
@@ -4646,10 +4671,7 @@
|
|
|
4646
4671
|
y1: .5,
|
|
4647
4672
|
r0: 0,
|
|
4648
4673
|
r1: 1,
|
|
4649
|
-
stops:
|
|
4650
|
-
color: item.value,
|
|
4651
|
-
offset: parseFloat(item.length.value) / 100
|
|
4652
|
-
}))
|
|
4674
|
+
stops: GradientParser.processColorStops(colorStops)
|
|
4653
4675
|
};
|
|
4654
4676
|
}
|
|
4655
4677
|
static ParseLinear(datum) {
|
|
@@ -4671,10 +4693,7 @@
|
|
|
4671
4693
|
y0: y0,
|
|
4672
4694
|
x1: x1,
|
|
4673
4695
|
y1: y1,
|
|
4674
|
-
stops:
|
|
4675
|
-
color: item.value,
|
|
4676
|
-
offset: parseFloat(item.length.value) / 100
|
|
4677
|
-
}))
|
|
4696
|
+
stops: GradientParser.processColorStops(colorStops)
|
|
4678
4697
|
};
|
|
4679
4698
|
}
|
|
4680
4699
|
}
|
|
@@ -12403,7 +12422,7 @@
|
|
|
12403
12422
|
case "right":
|
|
12404
12423
|
deltaX = -aabbBounds.width();
|
|
12405
12424
|
}
|
|
12406
|
-
return aabbBounds.translate(deltaX, deltaY), application.graphicService.updateTempAABBBounds(aabbBounds), null == attribute.forceBoundsHeight && null == attribute.forceBoundsWidth || application.graphicService.updateHTMLTextAABBBounds(attribute, richtextTheme, aabbBounds), this.widthWithoutTransform = aabbBounds.x2 - aabbBounds.x1, this.heightWithoutTransform = aabbBounds.y2 - aabbBounds.y1, application.graphicService.transformAABBBounds(attribute, aabbBounds, richtextTheme, !1, this), 0 === aabbBounds.width() && 0 === aabbBounds.height() && aabbBounds.clear(), aabbBounds;
|
|
12425
|
+
return height || ("middle" === this.verticalDirection ? deltaY -= aabbBounds.height() / 2 : "bottom" === this.verticalDirection && (deltaY -= aabbBounds.height())), aabbBounds.translate(deltaX, deltaY), application.graphicService.updateTempAABBBounds(aabbBounds), null == attribute.forceBoundsHeight && null == attribute.forceBoundsWidth || application.graphicService.updateHTMLTextAABBBounds(attribute, richtextTheme, aabbBounds), this.widthWithoutTransform = aabbBounds.x2 - aabbBounds.x1, this.heightWithoutTransform = aabbBounds.y2 - aabbBounds.y1, application.graphicService.transformAABBBounds(attribute, aabbBounds, richtextTheme, !1, this), 0 === aabbBounds.width() && 0 === aabbBounds.height() && aabbBounds.clear(), aabbBounds;
|
|
12407
12426
|
}
|
|
12408
12427
|
needUpdateTags(keys) {
|
|
12409
12428
|
return super.needUpdateTags(keys, RICHTEXT_UPDATE_TAG_KEY);
|
|
@@ -19167,6 +19186,7 @@
|
|
|
19167
19186
|
}));
|
|
19168
19187
|
}
|
|
19169
19188
|
tryShowInputBounds() {
|
|
19189
|
+
var _a, _b;
|
|
19170
19190
|
if (!this.currRt || !this.focusing) return;
|
|
19171
19191
|
const {
|
|
19172
19192
|
editOptions = {}
|
|
@@ -19182,6 +19202,8 @@
|
|
|
19182
19202
|
this.shadowBounds = this.shadowBounds || createRect({}), this.shadowBounds.setAttributes({
|
|
19183
19203
|
x: 0,
|
|
19184
19204
|
y: 0,
|
|
19205
|
+
scaleX: 1 / (null !== (_a = this.currRt.attribute.scaleX) && void 0 !== _a ? _a : 1),
|
|
19206
|
+
scaleY: 1 / (null !== (_b = this.currRt.attribute.scaleY) && void 0 !== _b ? _b : 1),
|
|
19185
19207
|
width: width,
|
|
19186
19208
|
height: height,
|
|
19187
19209
|
fill: !1,
|
|
@@ -19283,7 +19305,9 @@
|
|
|
19283
19305
|
y2 = getRichTextBounds(Object.assign(Object.assign({}, target.attribute), {
|
|
19284
19306
|
textConfig: [{
|
|
19285
19307
|
text: "a"
|
|
19286
|
-
}]
|
|
19308
|
+
}],
|
|
19309
|
+
scaleX: 1,
|
|
19310
|
+
scaleY: 1
|
|
19287
19311
|
})).height();
|
|
19288
19312
|
this.startCursorPos = {
|
|
19289
19313
|
x: x,
|
|
@@ -19319,7 +19343,10 @@
|
|
|
19319
19343
|
textConfig: [{
|
|
19320
19344
|
text: "a"
|
|
19321
19345
|
}]
|
|
19322
|
-
})), b = getRichTextBounds(
|
|
19346
|
+
})), b = getRichTextBounds(Object.assign(Object.assign({}, attr), {
|
|
19347
|
+
scaleX: 1,
|
|
19348
|
+
scaleY: 1
|
|
19349
|
+
}))), "middle" === textBaseline ? dy = -b.height() / 2 : "bottom" === textBaseline && (dy = -b.height()), this.editLine && this.editLine.setAttributes({
|
|
19323
19350
|
dy: dy
|
|
19324
19351
|
}), this.editBg && this.editBg.setAttributes({
|
|
19325
19352
|
dy: dy
|
|
@@ -19516,9 +19543,15 @@
|
|
|
19516
19543
|
} = rt.attribute;
|
|
19517
19544
|
let dy = 0;
|
|
19518
19545
|
if ("middle" === textBaseline) {
|
|
19519
|
-
dy = getRichTextBounds(rt.attribute)
|
|
19546
|
+
dy = getRichTextBounds(Object.assign(Object.assign({}, rt.attribute), {
|
|
19547
|
+
scaleX: 1,
|
|
19548
|
+
scaleY: 1
|
|
19549
|
+
})).height() / 2;
|
|
19520
19550
|
} else if ("bottom" === textBaseline) {
|
|
19521
|
-
dy = getRichTextBounds(rt.attribute)
|
|
19551
|
+
dy = getRichTextBounds(Object.assign(Object.assign({}, rt.attribute), {
|
|
19552
|
+
scaleX: 1,
|
|
19553
|
+
scaleY: 1
|
|
19554
|
+
})).height();
|
|
19522
19555
|
}
|
|
19523
19556
|
return p1.y += dy, p1;
|
|
19524
19557
|
}
|
|
@@ -30503,8 +30536,6 @@
|
|
|
30503
30536
|
}
|
|
30504
30537
|
onStart() {
|
|
30505
30538
|
super.onStart();
|
|
30506
|
-
}
|
|
30507
|
-
onFirstRun() {
|
|
30508
30539
|
const fromProps = this.getFromProps();
|
|
30509
30540
|
this.target.setAttributes(fromProps);
|
|
30510
30541
|
}
|
|
@@ -35149,11 +35180,1280 @@
|
|
|
35149
35180
|
}
|
|
35150
35181
|
}
|
|
35151
35182
|
|
|
35183
|
+
class DisappearAnimateBase extends AStageAnimate {
|
|
35184
|
+
constructor(from, to, duration, easing, params) {
|
|
35185
|
+
super(from, to, duration, easing, params), this.webglCanvas = null, this.gl = null, this.program = null, this.currentAnimationRatio = 0, this.animationTime = 0;
|
|
35186
|
+
}
|
|
35187
|
+
onUpdate(end, ratio, out) {
|
|
35188
|
+
super.onUpdate(end, ratio, out), this.currentAnimationRatio = ratio, this.animationTime = ratio * Math.PI * 2;
|
|
35189
|
+
}
|
|
35190
|
+
getAnimationTime() {
|
|
35191
|
+
return this.currentAnimationRatio > 0 ? this.animationTime : Date.now() / 1e3;
|
|
35192
|
+
}
|
|
35193
|
+
getDurationFromParent() {
|
|
35194
|
+
return this.duration || 1e3;
|
|
35195
|
+
}
|
|
35196
|
+
initWebGL(canvas) {
|
|
35197
|
+
try {
|
|
35198
|
+
if (this.webglCanvas = vglobal.createCanvas({
|
|
35199
|
+
width: canvas.width,
|
|
35200
|
+
height: canvas.height,
|
|
35201
|
+
dpr: vglobal.devicePixelRatio
|
|
35202
|
+
}), !this.webglCanvas) return console.warn("WebGL canvas creation failed"), !1;
|
|
35203
|
+
this.webglCanvas.style.width = canvas.style.width || `${canvas.width}px`, this.webglCanvas.style.height = canvas.style.height || `${canvas.height}px`;
|
|
35204
|
+
let glContext = null;
|
|
35205
|
+
try {
|
|
35206
|
+
glContext = this.webglCanvas.getContext("webgl"), glContext || (glContext = this.webglCanvas.getContext("experimental-webgl"));
|
|
35207
|
+
} catch (e) {
|
|
35208
|
+
console.warn("Failed to get WebGL context:", e);
|
|
35209
|
+
}
|
|
35210
|
+
if (this.gl = glContext, !this.gl) return console.warn("WebGL not supported"), !1;
|
|
35211
|
+
const shaders = this.getShaderSources();
|
|
35212
|
+
return this.program = this.createShaderProgram(shaders.vertex, shaders.fragment), null !== this.program;
|
|
35213
|
+
} catch (error) {
|
|
35214
|
+
return console.warn("Failed to initialize WebGL:", error), !1;
|
|
35215
|
+
}
|
|
35216
|
+
}
|
|
35217
|
+
createShaderProgram(vertexSource, fragmentSource) {
|
|
35218
|
+
if (!this.gl) return null;
|
|
35219
|
+
const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource),
|
|
35220
|
+
fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);
|
|
35221
|
+
if (!vertexShader || !fragmentShader) return null;
|
|
35222
|
+
const program = this.gl.createProgram();
|
|
35223
|
+
return program ? (this.gl.attachShader(program, vertexShader), this.gl.attachShader(program, fragmentShader), this.gl.linkProgram(program), this.gl.getProgramParameter(program, this.gl.LINK_STATUS) ? program : (console.error("Shader program link error:", this.gl.getProgramInfoLog(program)), null)) : null;
|
|
35224
|
+
}
|
|
35225
|
+
createShader(type, source) {
|
|
35226
|
+
if (!this.gl) return null;
|
|
35227
|
+
const shader = this.gl.createShader(type);
|
|
35228
|
+
return shader ? (this.gl.shaderSource(shader, source), this.gl.compileShader(shader), this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS) ? shader : (console.error("Shader compile error:", this.gl.getShaderInfoLog(shader)), this.gl.deleteShader(shader), null)) : null;
|
|
35229
|
+
}
|
|
35230
|
+
setupWebGLState(canvas) {
|
|
35231
|
+
this.gl && this.webglCanvas && (this.webglCanvas.width === canvas.width && this.webglCanvas.height === canvas.height || (this.webglCanvas.width = canvas.width, this.webglCanvas.height = canvas.height), this.gl.viewport(0, 0, this.webglCanvas.width, this.webglCanvas.height), this.gl.clearColor(0, 0, 0, 0), this.gl.clear(this.gl.COLOR_BUFFER_BIT));
|
|
35232
|
+
}
|
|
35233
|
+
createFullScreenQuad() {
|
|
35234
|
+
if (!this.gl) return null;
|
|
35235
|
+
const vertices = new Float32Array([-1, -1, 0, 1, 1, -1, 1, 1, -1, 1, 0, 0, 1, 1, 1, 0]),
|
|
35236
|
+
vertexBuffer = this.gl.createBuffer();
|
|
35237
|
+
return this.gl.bindBuffer(this.gl.ARRAY_BUFFER, vertexBuffer), this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW), vertexBuffer;
|
|
35238
|
+
}
|
|
35239
|
+
createTextureFromCanvas(canvas) {
|
|
35240
|
+
if (!this.gl) return null;
|
|
35241
|
+
const texture = this.gl.createTexture();
|
|
35242
|
+
return this.gl.activeTexture(this.gl.TEXTURE0), this.gl.bindTexture(this.gl.TEXTURE_2D, texture), this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.RGBA, this.gl.RGBA, this.gl.UNSIGNED_BYTE, canvas), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.CLAMP_TO_EDGE), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.CLAMP_TO_EDGE), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR), texture;
|
|
35243
|
+
}
|
|
35244
|
+
setupVertexAttributes() {
|
|
35245
|
+
if (!this.gl || !this.program) return;
|
|
35246
|
+
const positionLocation = this.gl.getAttribLocation(this.program, "a_position"),
|
|
35247
|
+
texCoordLocation = this.gl.getAttribLocation(this.program, "a_texCoord");
|
|
35248
|
+
this.gl.enableVertexAttribArray(positionLocation), this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, !1, 16, 0), this.gl.enableVertexAttribArray(texCoordLocation), this.gl.vertexAttribPointer(texCoordLocation, 2, this.gl.FLOAT, !1, 16, 8);
|
|
35249
|
+
}
|
|
35250
|
+
createOutputCanvas(canvas) {
|
|
35251
|
+
const outputCanvas = vglobal.createCanvas({
|
|
35252
|
+
width: canvas.width,
|
|
35253
|
+
height: canvas.height,
|
|
35254
|
+
dpr: vglobal.devicePixelRatio
|
|
35255
|
+
}),
|
|
35256
|
+
ctx = outputCanvas.getContext("2d");
|
|
35257
|
+
return ctx ? (ctx.clearRect(0, 0, canvas.width, canvas.height), ctx.drawImage(canvas, 0, 0), {
|
|
35258
|
+
canvas: outputCanvas,
|
|
35259
|
+
ctx: ctx
|
|
35260
|
+
}) : null;
|
|
35261
|
+
}
|
|
35262
|
+
getShaderSources() {
|
|
35263
|
+
return null;
|
|
35264
|
+
}
|
|
35265
|
+
applyWebGLEffect(canvas) {
|
|
35266
|
+
return null;
|
|
35267
|
+
}
|
|
35268
|
+
applyCanvas2DEffect(canvas) {
|
|
35269
|
+
return null;
|
|
35270
|
+
}
|
|
35271
|
+
supportsWebGL() {
|
|
35272
|
+
return null !== this.getShaderSources();
|
|
35273
|
+
}
|
|
35274
|
+
supportsCanvas2D() {
|
|
35275
|
+
return this.applyCanvas2DEffect !== DisappearAnimateBase.prototype.applyCanvas2DEffect;
|
|
35276
|
+
}
|
|
35277
|
+
release() {
|
|
35278
|
+
super.release(), this.gl && (this.program && (this.gl.deleteProgram(this.program), this.program = null), this.gl = null), this.webglCanvas && (this.webglCanvas = null), this.currentAnimationRatio = 0, this.animationTime = 0;
|
|
35279
|
+
}
|
|
35280
|
+
afterStageRender(stage, canvas) {
|
|
35281
|
+
let result = null;
|
|
35282
|
+
if (this.supportsWebGL() && (this.gl || this.initWebGL(canvas) || console.warn("WebGL初始化失败,尝试Canvas 2D回退"), this.gl)) {
|
|
35283
|
+
if (result = this.applyWebGLEffect(canvas), result) return result;
|
|
35284
|
+
console.warn("WebGL特效执行失败,尝试Canvas 2D回退");
|
|
35285
|
+
}
|
|
35286
|
+
if (this.supportsCanvas2D()) {
|
|
35287
|
+
if (result = this.applyCanvas2DEffect(canvas), result) return result;
|
|
35288
|
+
console.warn("Canvas 2D特效执行失败");
|
|
35289
|
+
}
|
|
35290
|
+
return this.supportsWebGL() || this.supportsCanvas2D() || console.error(`特效类 ${this.constructor.name} 未实现任何渲染方法。请实现 applyWebGLEffect 或 applyCanvas2DEffect 方法。`), canvas;
|
|
35291
|
+
}
|
|
35292
|
+
}
|
|
35293
|
+
|
|
35294
|
+
class Canvas2DEffectBase extends DisappearAnimateBase {
|
|
35295
|
+
constructor(from, to, duration, easing, params) {
|
|
35296
|
+
super(from, to, duration, easing, params);
|
|
35297
|
+
}
|
|
35298
|
+
getShaderSources() {
|
|
35299
|
+
return null;
|
|
35300
|
+
}
|
|
35301
|
+
applyWebGLEffect(canvas) {
|
|
35302
|
+
return null;
|
|
35303
|
+
}
|
|
35304
|
+
}
|
|
35305
|
+
class HybridEffectBase extends DisappearAnimateBase {
|
|
35306
|
+
constructor(from, to, duration, easing, params) {
|
|
35307
|
+
super(from, to, duration, easing, params);
|
|
35308
|
+
}
|
|
35309
|
+
getShaderSources() {
|
|
35310
|
+
return null;
|
|
35311
|
+
}
|
|
35312
|
+
applyWebGLEffect(canvas) {
|
|
35313
|
+
return null;
|
|
35314
|
+
}
|
|
35315
|
+
applyCanvas2DEffect(canvas) {
|
|
35316
|
+
return null;
|
|
35317
|
+
}
|
|
35318
|
+
supportsWebGL() {
|
|
35319
|
+
return this.getShaderSources !== HybridEffectBase.prototype.getShaderSources && null !== this.getShaderSources();
|
|
35320
|
+
}
|
|
35321
|
+
supportsCanvas2D() {
|
|
35322
|
+
return this.applyCanvas2DEffect !== HybridEffectBase.prototype.applyCanvas2DEffect;
|
|
35323
|
+
}
|
|
35324
|
+
afterStageRender(stage, canvas) {
|
|
35325
|
+
var _a, _b;
|
|
35326
|
+
let result = null;
|
|
35327
|
+
if (!1 !== (null === (_b = null === (_a = this.params) || void 0 === _a ? void 0 : _a.options) || void 0 === _b ? void 0 : _b.useWebGL)) {
|
|
35328
|
+
if (this.supportsWebGL() && (this.gl || this.initWebGL(canvas) || console.warn("WebGL初始化失败,尝试Canvas 2D回退"), this.gl)) {
|
|
35329
|
+
if (result = this.applyWebGLEffect(canvas), result) return result;
|
|
35330
|
+
console.warn("WebGL特效执行失败,尝试Canvas 2D回退");
|
|
35331
|
+
}
|
|
35332
|
+
if (this.supportsCanvas2D()) {
|
|
35333
|
+
if (result = this.applyCanvas2DEffect(canvas), result) return result;
|
|
35334
|
+
console.warn("Canvas 2D特效执行失败");
|
|
35335
|
+
}
|
|
35336
|
+
} else if (this.supportsCanvas2D()) {
|
|
35337
|
+
if (result = this.applyCanvas2DEffect(canvas), result) return result;
|
|
35338
|
+
console.warn("Canvas 2D特效执行失败");
|
|
35339
|
+
} else console.warn(`${this.constructor.name}: useWebGL=false 但未实现Canvas 2D方法`);
|
|
35340
|
+
return this.supportsWebGL() || this.supportsCanvas2D() || console.error(`特效类 ${this.constructor.name} 未实现任何渲染方法。请实现 applyWebGLEffect 或 applyCanvas2DEffect 方法。`), canvas;
|
|
35341
|
+
}
|
|
35342
|
+
}
|
|
35343
|
+
|
|
35344
|
+
class ImageProcessUtils {
|
|
35345
|
+
static createTempCanvas(width, height, dpr) {
|
|
35346
|
+
return vglobal.createCanvas({
|
|
35347
|
+
width: width,
|
|
35348
|
+
height: height,
|
|
35349
|
+
dpr: dpr || vglobal.devicePixelRatio
|
|
35350
|
+
});
|
|
35351
|
+
}
|
|
35352
|
+
static cloneImageData(imageData) {
|
|
35353
|
+
const clonedData = new Uint8ClampedArray(imageData.data);
|
|
35354
|
+
return new ImageData(clonedData, imageData.width, imageData.height);
|
|
35355
|
+
}
|
|
35356
|
+
static lerp(start, end, t) {
|
|
35357
|
+
return start * (1 - t) + end * t;
|
|
35358
|
+
}
|
|
35359
|
+
static smoothstep(edge0, edge1, x) {
|
|
35360
|
+
const t = Math.max(0, Math.min(1, (x - edge0) / (edge1 - edge0)));
|
|
35361
|
+
return t * t * (3 - 2 * t);
|
|
35362
|
+
}
|
|
35363
|
+
static distance(x1, y1, x2, y2) {
|
|
35364
|
+
const dx = x2 - x1,
|
|
35365
|
+
dy = y2 - y1;
|
|
35366
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
35367
|
+
}
|
|
35368
|
+
static normalizeAngle(angle) {
|
|
35369
|
+
return (angle + Math.PI) / (2 * Math.PI);
|
|
35370
|
+
}
|
|
35371
|
+
static pixelNoise(x, y, pixelSize) {
|
|
35372
|
+
if (pixelSize <= 0) return 0;
|
|
35373
|
+
const gridX = Math.floor(x / pixelSize) * pixelSize,
|
|
35374
|
+
gridY = Math.floor(y / pixelSize) * pixelSize,
|
|
35375
|
+
n = 43758.5453 * Math.sin(12.9898 * gridX + 78.233 * gridY);
|
|
35376
|
+
return n - Math.floor(n);
|
|
35377
|
+
}
|
|
35378
|
+
static generateNoiseTexture(width, height) {
|
|
35379
|
+
const data = new Uint8Array(width * height);
|
|
35380
|
+
for (let i = 0; i < data.length; i++) data[i] = Math.floor(256 * Math.random());
|
|
35381
|
+
return data;
|
|
35382
|
+
}
|
|
35383
|
+
static applyCSSFilter(canvas, filter) {
|
|
35384
|
+
const outputCanvas = this.createTempCanvas(canvas.width, canvas.height),
|
|
35385
|
+
ctx = outputCanvas.getContext("2d");
|
|
35386
|
+
return ctx ? (ctx.filter = filter, ctx.drawImage(canvas, 0, 0), ctx.filter = "none", outputCanvas) : canvas;
|
|
35387
|
+
}
|
|
35388
|
+
static extractChannel(imageData, channelIndex) {
|
|
35389
|
+
const {
|
|
35390
|
+
data: data,
|
|
35391
|
+
width: width,
|
|
35392
|
+
height: height
|
|
35393
|
+
} = imageData,
|
|
35394
|
+
channelData = new Uint8ClampedArray(data.length);
|
|
35395
|
+
for (let i = 0; i < data.length; i += 4) channelData[i] = 0, channelData[i + 1] = 0, channelData[i + 2] = 0, channelData[i + 3] = data[i + 3], channelIndex >= 0 && channelIndex <= 2 && (channelData[i + channelIndex] = data[i + channelIndex]);
|
|
35396
|
+
return new ImageData(channelData, width, height);
|
|
35397
|
+
}
|
|
35398
|
+
static blendImageData(imageData1, imageData2, ratio) {
|
|
35399
|
+
const {
|
|
35400
|
+
data: data1,
|
|
35401
|
+
width: width,
|
|
35402
|
+
height: height
|
|
35403
|
+
} = imageData1,
|
|
35404
|
+
{
|
|
35405
|
+
data: data2
|
|
35406
|
+
} = imageData2,
|
|
35407
|
+
result = new Uint8ClampedArray(data1.length);
|
|
35408
|
+
for (let i = 0; i < data1.length; i += 4) result[i] = Math.round(this.lerp(data1[i], data2[i], ratio)), result[i + 1] = Math.round(this.lerp(data1[i + 1], data2[i + 1], ratio)), result[i + 2] = Math.round(this.lerp(data1[i + 2], data2[i + 2], ratio)), result[i + 3] = Math.round(this.lerp(data1[i + 3], data2[i + 3], ratio));
|
|
35409
|
+
return new ImageData(result, width, height);
|
|
35410
|
+
}
|
|
35411
|
+
static getLuminance(r, g, b) {
|
|
35412
|
+
return .299 * r + .587 * g + .114 * b;
|
|
35413
|
+
}
|
|
35414
|
+
static applySepiaToPixel(r, g, b) {
|
|
35415
|
+
return [Math.min(255, .393 * r + .769 * g + .189 * b), Math.min(255, .349 * r + .686 * g + .168 * b), Math.min(255, .272 * r + .534 * g + .131 * b)];
|
|
35416
|
+
}
|
|
35417
|
+
static calculateDynamicStrength(baseStrength, animationTime) {
|
|
35418
|
+
return baseStrength * (animationTime / (2 * Math.PI));
|
|
35419
|
+
}
|
|
35420
|
+
}
|
|
35421
|
+
class ShaderLibrary {}
|
|
35422
|
+
ShaderLibrary.STANDARD_VERTEX_SHADER = "\n attribute vec2 a_position;\n attribute vec2 a_texCoord;\n varying vec2 v_texCoord;\n\n void main() {\n gl_Position = vec4(a_position, 0.0, 1.0);\n v_texCoord = a_texCoord;\n }\n ", ShaderLibrary.SHADER_FUNCTIONS = "\n // 亮度计算函数\n float luminance(vec3 color) {\n return dot(color, vec3(0.299, 0.587, 0.114));\n }\n\n // 褐色调函数\n vec3 sepia(vec3 color) {\n float r = color.r * 0.393 + color.g * 0.769 + color.b * 0.189;\n float g = color.r * 0.349 + color.g * 0.686 + color.b * 0.168;\n float b = color.r * 0.272 + color.g * 0.534 + color.b * 0.131;\n return vec3(r, g, b);\n }\n\n // 线性插值函数\n float lerp(float a, float b, float t) {\n return a * (1.0 - t) + b * t;\n }\n\n\n // 简单噪声函数\n float pixelNoise(vec2 coord, float pixelSize) {\n vec2 gridCoord = floor(coord / pixelSize) * pixelSize;\n return fract(sin(dot(gridCoord, vec2(12.9898, 78.233))) * 43758.5453123);\n }\n\n // 动态强度计算\n float calculateDynamicStrength(float baseStrength, float time) {\n return baseStrength * (time / 6.28318531); // 2π\n }\n ";
|
|
35423
|
+
|
|
35424
|
+
class Dissolve extends HybridEffectBase {
|
|
35425
|
+
constructor(from, to, duration, easing, params) {
|
|
35426
|
+
var _a, _b, _c, _d;
|
|
35427
|
+
super(from, to, duration, easing, params), this.noiseData = null;
|
|
35428
|
+
const rawNoiseScale = null === (_a = null == params ? void 0 : params.options) || void 0 === _a ? void 0 : _a.noiseScale,
|
|
35429
|
+
clampedNoiseScale = void 0 !== rawNoiseScale ? Math.max(0, Math.floor(rawNoiseScale)) : 8;
|
|
35430
|
+
this.dissolveConfig = {
|
|
35431
|
+
dissolveType: (null === (_b = null == params ? void 0 : params.options) || void 0 === _b ? void 0 : _b.dissolveType) || "outward",
|
|
35432
|
+
useWebGL: void 0 === (null === (_c = null == params ? void 0 : params.options) || void 0 === _c ? void 0 : _c.useWebGL) || params.options.useWebGL,
|
|
35433
|
+
noiseScale: clampedNoiseScale,
|
|
35434
|
+
fadeEdge: void 0 === (null === (_d = null == params ? void 0 : params.options) || void 0 === _d ? void 0 : _d.fadeEdge) || params.options.fadeEdge
|
|
35435
|
+
};
|
|
35436
|
+
}
|
|
35437
|
+
getShaderSources() {
|
|
35438
|
+
return {
|
|
35439
|
+
vertex: ShaderLibrary.STANDARD_VERTEX_SHADER,
|
|
35440
|
+
fragment: `\n precision mediump float;\n uniform sampler2D u_texture;\n uniform sampler2D u_noiseTexture;\n uniform float u_time;\n uniform int u_dissolveType;\n uniform vec2 u_resolution;\n uniform float u_noiseScale;\n uniform bool u_fadeEdge;\n varying vec2 v_texCoord;\n\n ${ShaderLibrary.SHADER_FUNCTIONS}\n\n // 向外溶解函数\n float outwardDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {\n vec2 center = vec2(0.5, 0.5);\n float distFromCenter = length(uv - center);\n float maxDist = length(vec2(0.5, 0.5));\n\n // 归一化距离 (0为中心,1为边缘)\n float normalizedDist = distFromCenter / maxDist;\n\n // 向外溶解:从边缘开始溶解,time控制溶解进度\n // 增加安全边距,确保动画结束时完全溶解\n float edgeThreshold = 1.2 - time * 1.5;\n\n // 当pixelSize > 0时添加颗粒效果\n if (pixelSize > 0.0) {\n // 添加基于像素大小的噪声,让边缘呈现颗粒状\n vec2 pixelCoord = uv * resolution; // 转换为像素坐标\n float noiseValue = pixelNoise(pixelCoord, pixelSize);\n float noiseInfluence = (noiseValue - 0.5) * 0.4; // 增强噪声影响\n edgeThreshold += noiseInfluence;\n return normalizedDist > edgeThreshold ? 0.0 : 1.0;\n } else {\n // 平滑溶解:根据fadeEdge决定是否使用渐变\n if (u_fadeEdge) {\n // 柔和边缘:返回渐变值\n float fadeWidth = 0.15; // 渐变宽度\n return 1.0 - smoothstep(edgeThreshold - fadeWidth, edgeThreshold, normalizedDist);\n } else {\n // 硬边缘:返回0或1\n return normalizedDist > edgeThreshold ? 0.0 : 1.0;\n }\n }\n }\n\n // 向内溶解函数\n float inwardDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {\n vec2 center = vec2(0.5, 0.5);\n float distFromCenter = length(uv - center);\n float maxDist = length(vec2(0.5, 0.5));\n\n float normalizedDist = distFromCenter / maxDist;\n\n // 向内溶解:从中心开始溶解,time控制溶解进度\n // 增加系数,确保动画结束时完全溶解\n float centerThreshold = time * 1.4;\n\n // 当pixelSize > 0时添加颗粒效果\n if (pixelSize > 0.0) {\n vec2 pixelCoord = uv * resolution;\n float noiseValue = pixelNoise(pixelCoord, pixelSize);\n float noiseInfluence = (noiseValue - 0.5) * 0.4;\n centerThreshold += noiseInfluence;\n return normalizedDist < centerThreshold ? 0.0 : 1.0;\n } else {\n // 平滑溶解:根据fadeEdge决定是否使用渐变\n if (u_fadeEdge) {\n // 柔和边缘:返回渐变值\n float fadeWidth = 0.15; // 渐变宽度\n return smoothstep(centerThreshold, centerThreshold + fadeWidth, normalizedDist);\n } else {\n // 硬边缘:返回0或1\n return normalizedDist < centerThreshold ? 0.0 : 1.0;\n }\n }\n }\n\n // 径向溶解函数\n float radialDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {\n vec2 center = vec2(0.5, 0.5);\n float angle = atan(uv.y - center.y, uv.x - center.x);\n float normalizedAngle = (angle + 3.14159) / (2.0 * 3.14159);\n\n // 径向溶解:按角度顺序溶解,time控制溶解进度\n // 增加系数,确保动画结束时完全溶解\n float angleThreshold = time * 1.2;\n\n // 当pixelSize > 0时添加颗粒效果\n if (pixelSize > 0.0) {\n vec2 pixelCoord = uv * resolution;\n float noiseValue = pixelNoise(pixelCoord, pixelSize);\n float noiseInfluence = (noiseValue - 0.5) * 0.3;\n angleThreshold += noiseInfluence;\n return normalizedAngle < angleThreshold ? 0.0 : 1.0;\n } else {\n // 平滑溶解:根据fadeEdge决定是否使用渐变\n if (u_fadeEdge) {\n // 柔和边缘:返回渐变值\n float fadeWidth = 0.08; // 渐变宽度\n return smoothstep(angleThreshold, angleThreshold + fadeWidth, normalizedAngle);\n } else {\n // 硬边缘:返回0或1\n return normalizedAngle < angleThreshold ? 0.0 : 1.0;\n }\n }\n }\n\n // 从左到右溶解函数\n float leftToRightDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {\n // 左到右溶解:从x=0开始向x=1溶解\n float dissolvePosition = time * 1.2; // 增加系数确保完全溶解\n\n // 当pixelSize > 0时添加颗粒效果\n if (pixelSize > 0.0) {\n vec2 pixelCoord = uv * resolution;\n float noiseValue = pixelNoise(pixelCoord, pixelSize);\n float noiseInfluence = (noiseValue - 0.5) * 0.3;\n dissolvePosition += noiseInfluence;\n return uv.x < dissolvePosition ? 0.0 : 1.0;\n } else {\n // 平滑溶解:根据fadeEdge决定是否使用渐变\n if (u_fadeEdge) {\n // 柔和边缘:返回渐变值\n float fadeWidth = 0.08; // 渐变宽度\n return smoothstep(dissolvePosition, dissolvePosition + fadeWidth, uv.x);\n } else {\n // 硬边缘:返回0或1\n return uv.x < dissolvePosition ? 0.0 : 1.0;\n }\n }\n }\n\n // 从右到左溶解函数\n float rightToLeftDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {\n // 右到左溶解:从x=1开始向x=0溶解\n float dissolvePosition = 1.0 - time * 1.2; // 增加系数确保完全溶解\n\n // 当pixelSize > 0时添加颗粒效果\n if (pixelSize > 0.0) {\n vec2 pixelCoord = uv * resolution;\n float noiseValue = pixelNoise(pixelCoord, pixelSize);\n float noiseInfluence = (noiseValue - 0.5) * 0.3;\n dissolvePosition += noiseInfluence;\n return uv.x > dissolvePosition ? 0.0 : 1.0;\n } else {\n // 平滑溶解:根据fadeEdge决定是否使用渐变\n if (u_fadeEdge) {\n // 柔和边缘:返回渐变值\n float fadeWidth = 0.08; // 渐变宽度\n return smoothstep(dissolvePosition - fadeWidth, dissolvePosition, uv.x);\n } else {\n // 硬边缘:返回0或1\n return uv.x > dissolvePosition ? 0.0 : 1.0;\n }\n }\n }\n\n // 从上到下溶解函数\n float topToBottomDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {\n // 上到下溶解:从y=0开始向y=1溶解\n float dissolvePosition = time * 1.2; // 增加系数确保完全溶解\n\n // 当pixelSize > 0时添加颗粒效果\n if (pixelSize > 0.0) {\n vec2 pixelCoord = uv * resolution;\n float noiseValue = pixelNoise(pixelCoord, pixelSize);\n float noiseInfluence = (noiseValue - 0.5) * 0.3;\n dissolvePosition += noiseInfluence;\n return uv.y < dissolvePosition ? 0.0 : 1.0;\n } else {\n // 平滑溶解:根据fadeEdge决定是否使用渐变\n if (u_fadeEdge) {\n // 柔和边缘:返回渐变值\n float fadeWidth = 0.08; // 渐变宽度\n return smoothstep(dissolvePosition, dissolvePosition + fadeWidth, uv.y);\n } else {\n // 硬边缘:返回0或1\n return uv.y < dissolvePosition ? 0.0 : 1.0;\n }\n }\n }\n\n // 从下到上溶解函数\n float bottomToTopDissolve(vec2 uv, float time, float pixelSize, vec2 resolution) {\n // 下到上溶解:从y=1开始向y=0溶解\n float dissolvePosition = 1.0 - time * 1.2; // 增加系数确保完全溶解\n\n // 当pixelSize > 0时添加颗粒效果\n if (pixelSize > 0.0) {\n vec2 pixelCoord = uv * resolution;\n float noiseValue = pixelNoise(pixelCoord, pixelSize);\n float noiseInfluence = (noiseValue - 0.5) * 0.3;\n dissolvePosition += noiseInfluence;\n return uv.y > dissolvePosition ? 0.0 : 1.0;\n } else {\n // 平滑溶解:根据fadeEdge决定是否使用渐变\n if (u_fadeEdge) {\n // 柔和边缘:返回渐变值\n float fadeWidth = 0.08; // 渐变宽度\n return smoothstep(dissolvePosition - fadeWidth, dissolvePosition, uv.y);\n } else {\n // 硬边缘:返回0或1\n return uv.y > dissolvePosition ? 0.0 : 1.0;\n }\n }\n }\n\n void main() {\n vec2 uv = v_texCoord;\n vec4 texColor = texture2D(u_texture, uv);\n\n float alpha = 1.0;\n\n // 根据溶解类型选择对应的溶解函数\n if (u_dissolveType == 0) {\n alpha = outwardDissolve(uv, u_time, u_noiseScale, u_resolution);\n } else if (u_dissolveType == 1) {\n alpha = inwardDissolve(uv, u_time, u_noiseScale, u_resolution);\n } else if (u_dissolveType == 2) {\n alpha = radialDissolve(uv, u_time, u_noiseScale, u_resolution);\n } else if (u_dissolveType == 3) {\n alpha = leftToRightDissolve(uv, u_time, u_noiseScale, u_resolution);\n } else if (u_dissolveType == 4) {\n alpha = rightToLeftDissolve(uv, u_time, u_noiseScale, u_resolution);\n } else if (u_dissolveType == 5) {\n alpha = topToBottomDissolve(uv, u_time, u_noiseScale, u_resolution);\n } else if (u_dissolveType == 6) {\n alpha = bottomToTopDissolve(uv, u_time, u_noiseScale, u_resolution);\n }\n\n gl_FragColor = vec4(texColor.rgb, texColor.a * alpha);\n }\n `
|
|
35441
|
+
};
|
|
35442
|
+
}
|
|
35443
|
+
applyWebGLEffect(canvas) {
|
|
35444
|
+
if (!this.gl || !this.program || !this.webglCanvas) return canvas;
|
|
35445
|
+
this.setupWebGLState(canvas);
|
|
35446
|
+
const texture = this.createTextureFromCanvas(canvas);
|
|
35447
|
+
if (!texture) return canvas;
|
|
35448
|
+
this.noiseData || (this.noiseData = ImageProcessUtils.generateNoiseTexture(256, 256));
|
|
35449
|
+
const noiseTexture = this.gl.createTexture();
|
|
35450
|
+
this.gl.activeTexture(this.gl.TEXTURE1), this.gl.bindTexture(this.gl.TEXTURE_2D, noiseTexture), this.gl.texImage2D(this.gl.TEXTURE_2D, 0, this.gl.LUMINANCE, 256, 256, 0, this.gl.LUMINANCE, this.gl.UNSIGNED_BYTE, this.noiseData), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_S, this.gl.REPEAT), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_WRAP_T, this.gl.REPEAT), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MIN_FILTER, this.gl.LINEAR), this.gl.texParameteri(this.gl.TEXTURE_2D, this.gl.TEXTURE_MAG_FILTER, this.gl.LINEAR);
|
|
35451
|
+
const vertexBuffer = this.createFullScreenQuad();
|
|
35452
|
+
return vertexBuffer ? (this.gl.useProgram(this.program), this.setupVertexAttributes(), this.setUniforms(), this.gl.enable(this.gl.BLEND), this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA), this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4), this.gl.deleteTexture(texture), this.gl.deleteTexture(noiseTexture), this.gl.deleteBuffer(vertexBuffer), this.webglCanvas) : canvas;
|
|
35453
|
+
}
|
|
35454
|
+
setUniforms() {
|
|
35455
|
+
if (!this.gl || !this.program || !this.webglCanvas) return;
|
|
35456
|
+
const textureLocation = this.gl.getUniformLocation(this.program, "u_texture"),
|
|
35457
|
+
noiseTextureLocation = this.gl.getUniformLocation(this.program, "u_noiseTexture"),
|
|
35458
|
+
timeLocation = this.gl.getUniformLocation(this.program, "u_time"),
|
|
35459
|
+
dissolveTypeLocation = this.gl.getUniformLocation(this.program, "u_dissolveType"),
|
|
35460
|
+
resolutionLocation = this.gl.getUniformLocation(this.program, "u_resolution"),
|
|
35461
|
+
noiseScaleLocation = this.gl.getUniformLocation(this.program, "u_noiseScale"),
|
|
35462
|
+
fadeEdgeLocation = this.gl.getUniformLocation(this.program, "u_fadeEdge");
|
|
35463
|
+
this.gl.uniform1i(textureLocation, 0), this.gl.uniform1i(noiseTextureLocation, 1), this.gl.uniform1f(timeLocation, this.currentAnimationRatio), this.gl.uniform2f(resolutionLocation, this.webglCanvas.width, this.webglCanvas.height), this.gl.uniform1f(noiseScaleLocation, this.dissolveConfig.noiseScale), this.gl.uniform1i(fadeEdgeLocation, this.dissolveConfig.fadeEdge ? 1 : 0);
|
|
35464
|
+
this.gl.uniform1i(dissolveTypeLocation, {
|
|
35465
|
+
outward: 0,
|
|
35466
|
+
inward: 1,
|
|
35467
|
+
radial: 2,
|
|
35468
|
+
leftToRight: 3,
|
|
35469
|
+
rightToLeft: 4,
|
|
35470
|
+
topToBottom: 5,
|
|
35471
|
+
bottomToTop: 6
|
|
35472
|
+
}[this.dissolveConfig.dissolveType] || 0);
|
|
35473
|
+
}
|
|
35474
|
+
applyCanvas2DEffect(canvas) {
|
|
35475
|
+
const outputCanvas = this.createOutputCanvas(canvas);
|
|
35476
|
+
if (!outputCanvas) return canvas;
|
|
35477
|
+
const {
|
|
35478
|
+
canvas: outputCanvasElement,
|
|
35479
|
+
ctx: ctx
|
|
35480
|
+
} = outputCanvas,
|
|
35481
|
+
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height),
|
|
35482
|
+
progress = this.currentAnimationRatio;
|
|
35483
|
+
let dissolvedImageData;
|
|
35484
|
+
switch (this.dissolveConfig.dissolveType) {
|
|
35485
|
+
case "outward":
|
|
35486
|
+
dissolvedImageData = this.applyOutwardDissolve(imageData, progress);
|
|
35487
|
+
break;
|
|
35488
|
+
case "inward":
|
|
35489
|
+
dissolvedImageData = this.applyInwardDissolve(imageData, progress);
|
|
35490
|
+
break;
|
|
35491
|
+
case "radial":
|
|
35492
|
+
dissolvedImageData = this.applyRadialDissolve(imageData, progress);
|
|
35493
|
+
break;
|
|
35494
|
+
case "leftToRight":
|
|
35495
|
+
dissolvedImageData = this.applyLeftToRightDissolve(imageData, progress);
|
|
35496
|
+
break;
|
|
35497
|
+
case "rightToLeft":
|
|
35498
|
+
dissolvedImageData = this.applyRightToLeftDissolve(imageData, progress);
|
|
35499
|
+
break;
|
|
35500
|
+
case "topToBottom":
|
|
35501
|
+
dissolvedImageData = this.applyTopToBottomDissolve(imageData, progress);
|
|
35502
|
+
break;
|
|
35503
|
+
case "bottomToTop":
|
|
35504
|
+
dissolvedImageData = this.applyBottomToTopDissolve(imageData, progress);
|
|
35505
|
+
break;
|
|
35506
|
+
default:
|
|
35507
|
+
dissolvedImageData = imageData;
|
|
35508
|
+
}
|
|
35509
|
+
return ctx.putImageData(dissolvedImageData, 0, 0), outputCanvasElement;
|
|
35510
|
+
}
|
|
35511
|
+
applyOutwardDissolve(imageData, progress) {
|
|
35512
|
+
const {
|
|
35513
|
+
data: data,
|
|
35514
|
+
width: width,
|
|
35515
|
+
height: height
|
|
35516
|
+
} = imageData,
|
|
35517
|
+
result = new Uint8ClampedArray(data.length);
|
|
35518
|
+
result.set(data);
|
|
35519
|
+
const centerX = width / 2,
|
|
35520
|
+
centerY = height / 2,
|
|
35521
|
+
maxDist = Math.sqrt(centerX * centerX + centerY * centerY),
|
|
35522
|
+
pixelSize = this.dissolveConfig.noiseScale;
|
|
35523
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
35524
|
+
const dx = x - centerX,
|
|
35525
|
+
dy = y - centerY,
|
|
35526
|
+
normalizedDist = Math.sqrt(dx * dx + dy * dy) / maxDist;
|
|
35527
|
+
let dissolveThreshold = 1.2 - 1.4 * progress,
|
|
35528
|
+
alpha = 1;
|
|
35529
|
+
if (pixelSize > 0) {
|
|
35530
|
+
dissolveThreshold += .4 * (ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5), alpha = normalizedDist > dissolveThreshold ? 0 : 1;
|
|
35531
|
+
} else if (this.dissolveConfig.fadeEdge) {
|
|
35532
|
+
const fadeStart = dissolveThreshold - .15;
|
|
35533
|
+
alpha = normalizedDist < fadeStart ? 1 : normalizedDist > dissolveThreshold ? 0 : 1 - (normalizedDist - fadeStart) / (dissolveThreshold - fadeStart);
|
|
35534
|
+
} else alpha = normalizedDist > dissolveThreshold ? 0 : 1;
|
|
35535
|
+
const index = 4 * (y * width + x);
|
|
35536
|
+
result[index + 3] = Math.floor(result[index + 3] * alpha);
|
|
35537
|
+
}
|
|
35538
|
+
return new ImageData(result, width, height);
|
|
35539
|
+
}
|
|
35540
|
+
applyInwardDissolve(imageData, progress) {
|
|
35541
|
+
const {
|
|
35542
|
+
data: data,
|
|
35543
|
+
width: width,
|
|
35544
|
+
height: height
|
|
35545
|
+
} = imageData,
|
|
35546
|
+
result = new Uint8ClampedArray(data.length);
|
|
35547
|
+
result.set(data);
|
|
35548
|
+
const centerX = width / 2,
|
|
35549
|
+
centerY = height / 2,
|
|
35550
|
+
maxDist = Math.sqrt(centerX * centerX + centerY * centerY),
|
|
35551
|
+
pixelSize = this.dissolveConfig.noiseScale;
|
|
35552
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
35553
|
+
const dx = x - centerX,
|
|
35554
|
+
dy = y - centerY,
|
|
35555
|
+
normalizedDist = Math.sqrt(dx * dx + dy * dy) / maxDist;
|
|
35556
|
+
let dissolveThreshold = 1.4 * progress,
|
|
35557
|
+
alpha = 1;
|
|
35558
|
+
if (pixelSize > 0) {
|
|
35559
|
+
dissolveThreshold += .4 * (ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5), alpha = normalizedDist < dissolveThreshold ? 0 : 1;
|
|
35560
|
+
} else if (this.dissolveConfig.fadeEdge) {
|
|
35561
|
+
const fadeEnd = dissolveThreshold + .15;
|
|
35562
|
+
alpha = normalizedDist < dissolveThreshold ? 0 : normalizedDist > fadeEnd ? 1 : (normalizedDist - dissolveThreshold) / (fadeEnd - dissolveThreshold);
|
|
35563
|
+
} else alpha = normalizedDist < dissolveThreshold ? 0 : 1;
|
|
35564
|
+
const index = 4 * (y * width + x);
|
|
35565
|
+
result[index + 3] = Math.floor(result[index + 3] * alpha);
|
|
35566
|
+
}
|
|
35567
|
+
return new ImageData(result, width, height);
|
|
35568
|
+
}
|
|
35569
|
+
applyRadialDissolve(imageData, progress) {
|
|
35570
|
+
const {
|
|
35571
|
+
data: data,
|
|
35572
|
+
width: width,
|
|
35573
|
+
height: height
|
|
35574
|
+
} = imageData,
|
|
35575
|
+
result = new Uint8ClampedArray(data.length);
|
|
35576
|
+
result.set(data);
|
|
35577
|
+
const centerX = width / 2,
|
|
35578
|
+
centerY = height / 2,
|
|
35579
|
+
pixelSize = this.dissolveConfig.noiseScale;
|
|
35580
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
35581
|
+
const dx = x - centerX,
|
|
35582
|
+
dy = y - centerY,
|
|
35583
|
+
normalizedAngle = (Math.atan2(dy, dx) + Math.PI) / (2 * Math.PI);
|
|
35584
|
+
let dissolveThreshold = 1.2 * progress,
|
|
35585
|
+
alpha = 1;
|
|
35586
|
+
if (pixelSize > 0) {
|
|
35587
|
+
dissolveThreshold += .3 * (ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5), alpha = normalizedAngle < dissolveThreshold ? 0 : 1;
|
|
35588
|
+
} else if (this.dissolveConfig.fadeEdge) {
|
|
35589
|
+
const fadeEnd = dissolveThreshold + .08;
|
|
35590
|
+
alpha = normalizedAngle < dissolveThreshold ? 0 : normalizedAngle > fadeEnd ? 1 : (normalizedAngle - dissolveThreshold) / (fadeEnd - dissolveThreshold);
|
|
35591
|
+
} else alpha = normalizedAngle < dissolveThreshold ? 0 : 1;
|
|
35592
|
+
const index = 4 * (y * width + x);
|
|
35593
|
+
result[index + 3] = Math.floor(result[index + 3] * alpha);
|
|
35594
|
+
}
|
|
35595
|
+
return new ImageData(result, width, height);
|
|
35596
|
+
}
|
|
35597
|
+
applyLeftToRightDissolve(imageData, progress) {
|
|
35598
|
+
const {
|
|
35599
|
+
data: data,
|
|
35600
|
+
width: width,
|
|
35601
|
+
height: height
|
|
35602
|
+
} = imageData,
|
|
35603
|
+
result = new Uint8ClampedArray(data.length);
|
|
35604
|
+
result.set(data);
|
|
35605
|
+
const pixelSize = this.dissolveConfig.noiseScale;
|
|
35606
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
35607
|
+
const normalizedX = x / width;
|
|
35608
|
+
let dissolveThreshold = 1.2 * progress,
|
|
35609
|
+
alpha = 1;
|
|
35610
|
+
if (pixelSize > 0) {
|
|
35611
|
+
dissolveThreshold += .3 * (ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5), alpha = normalizedX < dissolveThreshold ? 0 : 1;
|
|
35612
|
+
} else if (this.dissolveConfig.fadeEdge) {
|
|
35613
|
+
const fadeEnd = dissolveThreshold + .08;
|
|
35614
|
+
alpha = normalizedX < dissolveThreshold ? 0 : normalizedX > fadeEnd ? 1 : (normalizedX - dissolveThreshold) / (fadeEnd - dissolveThreshold);
|
|
35615
|
+
} else alpha = normalizedX < dissolveThreshold ? 0 : 1;
|
|
35616
|
+
const index = 4 * (y * width + x);
|
|
35617
|
+
result[index + 3] = Math.floor(result[index + 3] * alpha);
|
|
35618
|
+
}
|
|
35619
|
+
return new ImageData(result, width, height);
|
|
35620
|
+
}
|
|
35621
|
+
applyRightToLeftDissolve(imageData, progress) {
|
|
35622
|
+
const {
|
|
35623
|
+
data: data,
|
|
35624
|
+
width: width,
|
|
35625
|
+
height: height
|
|
35626
|
+
} = imageData,
|
|
35627
|
+
result = new Uint8ClampedArray(data.length);
|
|
35628
|
+
result.set(data);
|
|
35629
|
+
const pixelSize = this.dissolveConfig.noiseScale;
|
|
35630
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
35631
|
+
const normalizedX = x / width;
|
|
35632
|
+
let dissolveThreshold = 1 - 1.2 * progress,
|
|
35633
|
+
alpha = 1;
|
|
35634
|
+
if (pixelSize > 0) {
|
|
35635
|
+
dissolveThreshold += .3 * (ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5), alpha = normalizedX > dissolveThreshold ? 0 : 1;
|
|
35636
|
+
} else if (this.dissolveConfig.fadeEdge) {
|
|
35637
|
+
const fadeStart = dissolveThreshold - .08;
|
|
35638
|
+
alpha = normalizedX < fadeStart ? 1 : normalizedX > dissolveThreshold ? 0 : 1 - (normalizedX - fadeStart) / (dissolveThreshold - fadeStart);
|
|
35639
|
+
} else alpha = normalizedX > dissolveThreshold ? 0 : 1;
|
|
35640
|
+
const index = 4 * (y * width + x);
|
|
35641
|
+
result[index + 3] = Math.floor(result[index + 3] * alpha);
|
|
35642
|
+
}
|
|
35643
|
+
return new ImageData(result, width, height);
|
|
35644
|
+
}
|
|
35645
|
+
applyTopToBottomDissolve(imageData, progress) {
|
|
35646
|
+
const {
|
|
35647
|
+
data: data,
|
|
35648
|
+
width: width,
|
|
35649
|
+
height: height
|
|
35650
|
+
} = imageData,
|
|
35651
|
+
result = new Uint8ClampedArray(data.length);
|
|
35652
|
+
result.set(data);
|
|
35653
|
+
const pixelSize = this.dissolveConfig.noiseScale;
|
|
35654
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
35655
|
+
const normalizedY = y / height;
|
|
35656
|
+
let dissolveThreshold = 1.2 * progress,
|
|
35657
|
+
alpha = 1;
|
|
35658
|
+
if (pixelSize > 0) {
|
|
35659
|
+
dissolveThreshold += .3 * (ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5), alpha = normalizedY < dissolveThreshold ? 0 : 1;
|
|
35660
|
+
} else if (this.dissolveConfig.fadeEdge) {
|
|
35661
|
+
const fadeEnd = dissolveThreshold + .08;
|
|
35662
|
+
alpha = normalizedY < dissolveThreshold ? 0 : normalizedY > fadeEnd ? 1 : (normalizedY - dissolveThreshold) / (fadeEnd - dissolveThreshold);
|
|
35663
|
+
} else alpha = normalizedY < dissolveThreshold ? 0 : 1;
|
|
35664
|
+
const index = 4 * (y * width + x);
|
|
35665
|
+
result[index + 3] = Math.floor(result[index + 3] * alpha);
|
|
35666
|
+
}
|
|
35667
|
+
return new ImageData(result, width, height);
|
|
35668
|
+
}
|
|
35669
|
+
applyBottomToTopDissolve(imageData, progress) {
|
|
35670
|
+
const {
|
|
35671
|
+
data: data,
|
|
35672
|
+
width: width,
|
|
35673
|
+
height: height
|
|
35674
|
+
} = imageData,
|
|
35675
|
+
result = new Uint8ClampedArray(data.length);
|
|
35676
|
+
result.set(data);
|
|
35677
|
+
const pixelSize = this.dissolveConfig.noiseScale;
|
|
35678
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
35679
|
+
const normalizedY = y / height;
|
|
35680
|
+
let dissolveThreshold = 1 - 1.2 * progress,
|
|
35681
|
+
alpha = 1;
|
|
35682
|
+
if (pixelSize > 0) {
|
|
35683
|
+
dissolveThreshold += .3 * (ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5), alpha = normalizedY > dissolveThreshold ? 0 : 1;
|
|
35684
|
+
} else if (this.dissolveConfig.fadeEdge) {
|
|
35685
|
+
const fadeStart = dissolveThreshold - .08;
|
|
35686
|
+
alpha = normalizedY < fadeStart ? 1 : normalizedY > dissolveThreshold ? 0 : 1 - (normalizedY - fadeStart) / (dissolveThreshold - fadeStart);
|
|
35687
|
+
} else alpha = normalizedY > dissolveThreshold ? 0 : 1;
|
|
35688
|
+
const index = 4 * (y * width + x);
|
|
35689
|
+
result[index + 3] = Math.floor(result[index + 3] * alpha);
|
|
35690
|
+
}
|
|
35691
|
+
return new ImageData(result, width, height);
|
|
35692
|
+
}
|
|
35693
|
+
}
|
|
35694
|
+
|
|
35695
|
+
class Grayscale extends HybridEffectBase {
|
|
35696
|
+
constructor(from, to, duration, easing, params) {
|
|
35697
|
+
var _a, _b, _c;
|
|
35698
|
+
super(from, to, duration, easing, params);
|
|
35699
|
+
const rawStrength = void 0 !== (null === (_a = null == params ? void 0 : params.options) || void 0 === _a ? void 0 : _a.strength) ? params.options.strength : 1,
|
|
35700
|
+
clampedStrength = Math.max(0, Math.min(1, rawStrength));
|
|
35701
|
+
this.colorConfig = {
|
|
35702
|
+
effectType: (null === (_b = null == params ? void 0 : params.options) || void 0 === _b ? void 0 : _b.effectType) || "grayscale",
|
|
35703
|
+
strength: clampedStrength,
|
|
35704
|
+
useWebGL: void 0 === (null === (_c = null == params ? void 0 : params.options) || void 0 === _c ? void 0 : _c.useWebGL) || params.options.useWebGL
|
|
35705
|
+
};
|
|
35706
|
+
}
|
|
35707
|
+
getShaderSources() {
|
|
35708
|
+
return {
|
|
35709
|
+
vertex: ShaderLibrary.STANDARD_VERTEX_SHADER,
|
|
35710
|
+
fragment: `\n precision mediump float;\n uniform sampler2D u_texture;\n uniform float u_time;\n uniform float u_strength;\n uniform int u_effectType;\n uniform vec2 u_resolution;\n varying vec2 v_texCoord;\n\n ${ShaderLibrary.SHADER_FUNCTIONS}\n\n void main() {\n vec2 uv = v_texCoord;\n vec4 originalColor = texture2D(u_texture, uv);\n vec3 color = originalColor.rgb;\n\n // 计算动态强度\n float dynamicStrength = calculateDynamicStrength(u_strength, u_time);\n\n if (u_effectType == 0) {\n // 灰度效果\n float gray = luminance(color);\n vec3 grayColor = vec3(gray);\n color = mix(color, grayColor, dynamicStrength);\n } else if (u_effectType == 1) {\n // 褐色调效果\n vec3 sepiaColor = sepia(color);\n color = mix(color, sepiaColor, dynamicStrength);\n }\n\n gl_FragColor = vec4(color, originalColor.a);\n }\n `
|
|
35711
|
+
};
|
|
35712
|
+
}
|
|
35713
|
+
applyWebGLEffect(canvas) {
|
|
35714
|
+
if (!this.gl || !this.program || !this.webglCanvas) return null;
|
|
35715
|
+
this.setupWebGLState(canvas);
|
|
35716
|
+
const texture = this.createTextureFromCanvas(canvas);
|
|
35717
|
+
if (!texture) return null;
|
|
35718
|
+
const vertexBuffer = this.createFullScreenQuad();
|
|
35719
|
+
if (!vertexBuffer) return this.gl.deleteTexture(texture), null;
|
|
35720
|
+
try {
|
|
35721
|
+
return this.gl.useProgram(this.program), this.setupVertexAttributes(), this.setColorUniforms(), this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4), this.webglCanvas;
|
|
35722
|
+
} finally {
|
|
35723
|
+
this.gl.deleteTexture(texture), this.gl.deleteBuffer(vertexBuffer);
|
|
35724
|
+
}
|
|
35725
|
+
}
|
|
35726
|
+
setColorUniforms() {
|
|
35727
|
+
if (!this.gl || !this.program) return;
|
|
35728
|
+
const currentTime = this.getAnimationTime(),
|
|
35729
|
+
timeLocation = this.gl.getUniformLocation(this.program, "u_time"),
|
|
35730
|
+
strengthLocation = this.gl.getUniformLocation(this.program, "u_strength"),
|
|
35731
|
+
effectTypeLocation = this.gl.getUniformLocation(this.program, "u_effectType"),
|
|
35732
|
+
resolutionLocation = this.gl.getUniformLocation(this.program, "u_resolution");
|
|
35733
|
+
this.gl.uniform1f(timeLocation, currentTime), this.gl.uniform1f(strengthLocation, this.colorConfig.strength), this.gl.uniform2f(resolutionLocation, this.webglCanvas.width, this.webglCanvas.height);
|
|
35734
|
+
this.gl.uniform1i(effectTypeLocation, {
|
|
35735
|
+
grayscale: 0,
|
|
35736
|
+
sepia: 1
|
|
35737
|
+
}[this.colorConfig.effectType] || 0);
|
|
35738
|
+
}
|
|
35739
|
+
applyCanvas2DEffect(canvas) {
|
|
35740
|
+
if (this.colorConfig.strength <= 0) {
|
|
35741
|
+
const outputCanvas = this.createOutputCanvas(canvas);
|
|
35742
|
+
return outputCanvas ? outputCanvas.canvas : null;
|
|
35743
|
+
}
|
|
35744
|
+
if (this.canUseCSSFilter()) return this.applyCSSFilter(canvas);
|
|
35745
|
+
const outputCanvas = this.createOutputCanvas(canvas);
|
|
35746
|
+
if (!outputCanvas) return null;
|
|
35747
|
+
const {
|
|
35748
|
+
ctx: ctx
|
|
35749
|
+
} = outputCanvas;
|
|
35750
|
+
try {
|
|
35751
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height),
|
|
35752
|
+
currentTime = this.getAnimationTime();
|
|
35753
|
+
let processedImageData;
|
|
35754
|
+
switch (this.colorConfig.effectType) {
|
|
35755
|
+
case "grayscale":
|
|
35756
|
+
default:
|
|
35757
|
+
processedImageData = this.applyGrayscaleEffect(imageData, this.colorConfig.strength, currentTime);
|
|
35758
|
+
break;
|
|
35759
|
+
case "sepia":
|
|
35760
|
+
processedImageData = this.applySepiaEffect(imageData, this.colorConfig.strength, currentTime);
|
|
35761
|
+
}
|
|
35762
|
+
return ctx.clearRect(0, 0, canvas.width, canvas.height), ctx.putImageData(processedImageData, 0, 0), outputCanvas.canvas;
|
|
35763
|
+
} catch (error) {
|
|
35764
|
+
return console.warn("Canvas 2D color effect failed:", error), null;
|
|
35765
|
+
}
|
|
35766
|
+
}
|
|
35767
|
+
canUseCSSFilter() {
|
|
35768
|
+
var _a;
|
|
35769
|
+
return !!window.useFilterAPI && "undefined" != typeof CSS && (null === (_a = CSS.supports) || void 0 === _a ? void 0 : _a.call(CSS, "filter", "grayscale(1)"));
|
|
35770
|
+
}
|
|
35771
|
+
applyCSSFilter(canvas) {
|
|
35772
|
+
try {
|
|
35773
|
+
const outputCanvas = ImageProcessUtils.createTempCanvas(canvas.width, canvas.height),
|
|
35774
|
+
ctx = outputCanvas.getContext("2d");
|
|
35775
|
+
if (!ctx) return null;
|
|
35776
|
+
const currentTime = this.getAnimationTime(),
|
|
35777
|
+
dynamicStrength = ImageProcessUtils.calculateDynamicStrength(this.colorConfig.strength, currentTime);
|
|
35778
|
+
let filterValue = "";
|
|
35779
|
+
return "grayscale" === this.colorConfig.effectType ? filterValue = `grayscale(${Math.min(1, dynamicStrength)})` : "sepia" === this.colorConfig.effectType && (filterValue = `sepia(${Math.min(1, dynamicStrength)})`), ctx.filter = filterValue, ctx.drawImage(canvas, 0, 0), ctx.filter = "none", outputCanvas;
|
|
35780
|
+
} catch (error) {
|
|
35781
|
+
return console.warn("CSS Filter API failed, falling back to pixel processing:", error), null;
|
|
35782
|
+
}
|
|
35783
|
+
}
|
|
35784
|
+
applyGrayscaleEffect(imageData, strength, time) {
|
|
35785
|
+
const {
|
|
35786
|
+
data: data,
|
|
35787
|
+
width: width,
|
|
35788
|
+
height: height
|
|
35789
|
+
} = imageData,
|
|
35790
|
+
result = new Uint8ClampedArray(data.length),
|
|
35791
|
+
dynamicStrength = ImageProcessUtils.calculateDynamicStrength(strength, time);
|
|
35792
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
35793
|
+
const r = data[i],
|
|
35794
|
+
g = data[i + 1],
|
|
35795
|
+
b = data[i + 2],
|
|
35796
|
+
a = data[i + 3],
|
|
35797
|
+
gray = ImageProcessUtils.getLuminance(r, g, b);
|
|
35798
|
+
result[i] = Math.round(ImageProcessUtils.lerp(r, gray, dynamicStrength)), result[i + 1] = Math.round(ImageProcessUtils.lerp(g, gray, dynamicStrength)), result[i + 2] = Math.round(ImageProcessUtils.lerp(b, gray, dynamicStrength)), result[i + 3] = a;
|
|
35799
|
+
}
|
|
35800
|
+
return new ImageData(result, width, height);
|
|
35801
|
+
}
|
|
35802
|
+
applySepiaEffect(imageData, strength, time) {
|
|
35803
|
+
const {
|
|
35804
|
+
data: data,
|
|
35805
|
+
width: width,
|
|
35806
|
+
height: height
|
|
35807
|
+
} = imageData,
|
|
35808
|
+
result = new Uint8ClampedArray(data.length),
|
|
35809
|
+
dynamicStrength = ImageProcessUtils.calculateDynamicStrength(strength, time);
|
|
35810
|
+
for (let i = 0; i < data.length; i += 4) {
|
|
35811
|
+
const r = data[i],
|
|
35812
|
+
g = data[i + 1],
|
|
35813
|
+
b = data[i + 2],
|
|
35814
|
+
a = data[i + 3],
|
|
35815
|
+
[sepiaR, sepiaG, sepiaB] = ImageProcessUtils.applySepiaToPixel(r, g, b);
|
|
35816
|
+
result[i] = Math.round(ImageProcessUtils.lerp(r, sepiaR, dynamicStrength)), result[i + 1] = Math.round(ImageProcessUtils.lerp(g, sepiaG, dynamicStrength)), result[i + 2] = Math.round(ImageProcessUtils.lerp(b, sepiaB, dynamicStrength)), result[i + 3] = a;
|
|
35817
|
+
}
|
|
35818
|
+
return new ImageData(result, width, height);
|
|
35819
|
+
}
|
|
35820
|
+
afterStageRender(stage, canvas) {
|
|
35821
|
+
if (this.canUseCSSFilter() && this.colorConfig.strength > 0) {
|
|
35822
|
+
const cssResult = this.applyCSSFilter(canvas);
|
|
35823
|
+
if (cssResult) return cssResult;
|
|
35824
|
+
}
|
|
35825
|
+
return super.afterStageRender(stage, canvas);
|
|
35826
|
+
}
|
|
35827
|
+
}
|
|
35828
|
+
|
|
35829
|
+
class Distortion extends HybridEffectBase {
|
|
35830
|
+
constructor(from, to, duration, easing, params) {
|
|
35831
|
+
var _a, _b, _c;
|
|
35832
|
+
super(from, to, duration, easing, params), this.distortionConfig = {
|
|
35833
|
+
distortionType: (null === (_a = null == params ? void 0 : params.options) || void 0 === _a ? void 0 : _a.distortionType) || "wave",
|
|
35834
|
+
strength: (null === (_b = null == params ? void 0 : params.options) || void 0 === _b ? void 0 : _b.strength) || .3,
|
|
35835
|
+
useWebGL: void 0 === (null === (_c = null == params ? void 0 : params.options) || void 0 === _c ? void 0 : _c.useWebGL) || params.options.useWebGL
|
|
35836
|
+
};
|
|
35837
|
+
}
|
|
35838
|
+
getShaderSources() {
|
|
35839
|
+
return {
|
|
35840
|
+
vertex: "\n attribute vec2 a_position;\n attribute vec2 a_texCoord;\n varying vec2 v_texCoord;\n\n void main() {\n gl_Position = vec4(a_position, 0.0, 1.0);\n v_texCoord = a_texCoord;\n }\n ",
|
|
35841
|
+
fragment: "\n precision mediump float;\n uniform sampler2D u_texture;\n uniform float u_time;\n uniform float u_strength;\n uniform int u_distortionType;\n uniform vec2 u_resolution;\n varying vec2 v_texCoord;\n\n // 波浪扭曲函数\n vec2 wave(vec2 uv, float time, float strength) {\n float waveX = sin(uv.y * 10.0 + time * 3.0) * strength * 0.1;\n float waveY = sin(uv.x * 10.0 + time * 2.0) * strength * 0.1;\n return uv + vec2(waveX, waveY);\n }\n\n // 涟漪扭曲函数\n vec2 ripple(vec2 uv, float time, float strength) {\n vec2 center = vec2(0.5, 0.5);\n float distance = length(uv - center);\n float ripple = sin(distance * 20.0 - time * 5.0) * strength * 0.1;\n vec2 direction = normalize(uv - center);\n return uv + direction * ripple;\n }\n\n // 漩涡扭曲函数\n vec2 swirl(vec2 uv, float time, float strength) {\n vec2 center = vec2(0.5, 0.5);\n vec2 delta = uv - center;\n float dist = length(delta);\n float originalAngle = atan(delta.y, delta.x);\n float rotationAngle = dist * strength * time * 2.0;\n float finalAngle = originalAngle + rotationAngle;\n return center + dist * vec2(cos(finalAngle), sin(finalAngle));\n }\n\n void main() {\n vec2 uv = v_texCoord;\n\n // 根据扭曲类型应用相应变换\n if (u_distortionType == 0) {\n uv = wave(uv, u_time, u_strength);\n } else if (u_distortionType == 1) {\n uv = ripple(uv, u_time, u_strength);\n } else if (u_distortionType == 2) {\n uv = swirl(uv, u_time, u_strength);\n }\n\n // 边界检查\n if (uv.x < 0.0 || uv.x > 1.0 || uv.y < 0.0 || uv.y > 1.0) {\n gl_FragColor = vec4(0.0, 0.0, 0.0, 0.0);\n } else {\n gl_FragColor = texture2D(u_texture, uv);\n }\n }\n "
|
|
35842
|
+
};
|
|
35843
|
+
}
|
|
35844
|
+
applyWebGLEffect(canvas) {
|
|
35845
|
+
if (!this.gl || !this.program || !this.webglCanvas) return null;
|
|
35846
|
+
this.setupWebGLState(canvas);
|
|
35847
|
+
const texture = this.createTextureFromCanvas(canvas);
|
|
35848
|
+
if (!texture) return null;
|
|
35849
|
+
const vertexBuffer = this.createFullScreenQuad();
|
|
35850
|
+
if (!vertexBuffer) return this.gl.deleteTexture(texture), null;
|
|
35851
|
+
try {
|
|
35852
|
+
return this.gl.useProgram(this.program), this.setupVertexAttributes(), this.setDistortionUniforms(), this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4), this.webglCanvas;
|
|
35853
|
+
} finally {
|
|
35854
|
+
this.gl.deleteTexture(texture), this.gl.deleteBuffer(vertexBuffer);
|
|
35855
|
+
}
|
|
35856
|
+
}
|
|
35857
|
+
setDistortionUniforms() {
|
|
35858
|
+
if (!this.gl || !this.program) return;
|
|
35859
|
+
const currentTime = this.getAnimationTime(),
|
|
35860
|
+
timeLocation = this.gl.getUniformLocation(this.program, "u_time"),
|
|
35861
|
+
strengthLocation = this.gl.getUniformLocation(this.program, "u_strength"),
|
|
35862
|
+
distortionTypeLocation = this.gl.getUniformLocation(this.program, "u_distortionType"),
|
|
35863
|
+
resolutionLocation = this.gl.getUniformLocation(this.program, "u_resolution");
|
|
35864
|
+
this.gl.uniform1f(timeLocation, currentTime), this.gl.uniform1f(strengthLocation, this.distortionConfig.strength), this.gl.uniform2f(resolutionLocation, this.webglCanvas.width, this.webglCanvas.height);
|
|
35865
|
+
this.gl.uniform1i(distortionTypeLocation, {
|
|
35866
|
+
wave: 0,
|
|
35867
|
+
ripple: 1,
|
|
35868
|
+
swirl: 2
|
|
35869
|
+
}[this.distortionConfig.distortionType] || 0);
|
|
35870
|
+
}
|
|
35871
|
+
applyCanvas2DEffect(canvas) {
|
|
35872
|
+
const outputCanvas = this.createOutputCanvas(canvas);
|
|
35873
|
+
if (!outputCanvas) return null;
|
|
35874
|
+
const {
|
|
35875
|
+
ctx: ctx
|
|
35876
|
+
} = outputCanvas;
|
|
35877
|
+
try {
|
|
35878
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height),
|
|
35879
|
+
currentTime = this.getAnimationTime();
|
|
35880
|
+
let distortedImageData;
|
|
35881
|
+
switch (this.distortionConfig.distortionType) {
|
|
35882
|
+
case "wave":
|
|
35883
|
+
distortedImageData = this.applyWaveDistortion(imageData, this.distortionConfig.strength, currentTime);
|
|
35884
|
+
break;
|
|
35885
|
+
case "ripple":
|
|
35886
|
+
distortedImageData = this.applyRippleDistortion(imageData, this.distortionConfig.strength, currentTime);
|
|
35887
|
+
break;
|
|
35888
|
+
case "swirl":
|
|
35889
|
+
distortedImageData = this.applySwirlDistortion(imageData, this.distortionConfig.strength, currentTime);
|
|
35890
|
+
break;
|
|
35891
|
+
default:
|
|
35892
|
+
distortedImageData = imageData;
|
|
35893
|
+
}
|
|
35894
|
+
return ctx.clearRect(0, 0, canvas.width, canvas.height), ctx.putImageData(distortedImageData, 0, 0), outputCanvas.canvas;
|
|
35895
|
+
} catch (error) {
|
|
35896
|
+
return console.warn("Canvas 2D distortion effect failed:", error), null;
|
|
35897
|
+
}
|
|
35898
|
+
}
|
|
35899
|
+
applyWaveDistortion(imageData, strength, time) {
|
|
35900
|
+
const {
|
|
35901
|
+
data: data,
|
|
35902
|
+
width: width,
|
|
35903
|
+
height: height
|
|
35904
|
+
} = imageData,
|
|
35905
|
+
result = new Uint8ClampedArray(data.length);
|
|
35906
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
35907
|
+
const waveX = Math.sin(.1 * y + 3 * time) * strength * 20,
|
|
35908
|
+
waveY = Math.sin(.1 * x + 2 * time) * strength * 20,
|
|
35909
|
+
sourceX = Math.round(x - waveX),
|
|
35910
|
+
sourceY = Math.round(y - waveY),
|
|
35911
|
+
targetIndex = 4 * (y * width + x);
|
|
35912
|
+
if (sourceX >= 0 && sourceX < width && sourceY >= 0 && sourceY < height) {
|
|
35913
|
+
const sourceIndex = 4 * (sourceY * width + sourceX);
|
|
35914
|
+
result[targetIndex] = data[sourceIndex], result[targetIndex + 1] = data[sourceIndex + 1], result[targetIndex + 2] = data[sourceIndex + 2], result[targetIndex + 3] = data[sourceIndex + 3];
|
|
35915
|
+
} else result[targetIndex + 3] = 0;
|
|
35916
|
+
}
|
|
35917
|
+
return new ImageData(result, width, height);
|
|
35918
|
+
}
|
|
35919
|
+
applyRippleDistortion(imageData, strength, time) {
|
|
35920
|
+
const {
|
|
35921
|
+
data: data,
|
|
35922
|
+
width: width,
|
|
35923
|
+
height: height
|
|
35924
|
+
} = imageData,
|
|
35925
|
+
result = new Uint8ClampedArray(data.length),
|
|
35926
|
+
centerX = width / 2,
|
|
35927
|
+
centerY = height / 2;
|
|
35928
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
35929
|
+
const dx = x - centerX,
|
|
35930
|
+
dy = y - centerY,
|
|
35931
|
+
distance = Math.sqrt(dx * dx + dy * dy),
|
|
35932
|
+
ripple = Math.sin(.2 * distance - 5 * time) * strength * 10,
|
|
35933
|
+
angle = Math.atan2(dy, dx),
|
|
35934
|
+
sourceX = Math.round(x - Math.cos(angle) * ripple),
|
|
35935
|
+
sourceY = Math.round(y - Math.sin(angle) * ripple),
|
|
35936
|
+
targetIndex = 4 * (y * width + x);
|
|
35937
|
+
if (sourceX >= 0 && sourceX < width && sourceY >= 0 && sourceY < height) {
|
|
35938
|
+
const sourceIndex = 4 * (sourceY * width + sourceX);
|
|
35939
|
+
result[targetIndex] = data[sourceIndex], result[targetIndex + 1] = data[sourceIndex + 1], result[targetIndex + 2] = data[sourceIndex + 2], result[targetIndex + 3] = data[sourceIndex + 3];
|
|
35940
|
+
} else result[targetIndex + 3] = 0;
|
|
35941
|
+
}
|
|
35942
|
+
return new ImageData(result, width, height);
|
|
35943
|
+
}
|
|
35944
|
+
applySwirlDistortion(imageData, strength, time) {
|
|
35945
|
+
const {
|
|
35946
|
+
data: data,
|
|
35947
|
+
width: width,
|
|
35948
|
+
height: height
|
|
35949
|
+
} = imageData,
|
|
35950
|
+
result = new Uint8ClampedArray(data.length),
|
|
35951
|
+
centerX = width / 2,
|
|
35952
|
+
centerY = height / 2;
|
|
35953
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
35954
|
+
const dx = x - centerX,
|
|
35955
|
+
dy = y - centerY,
|
|
35956
|
+
distance = Math.sqrt(dx * dx + dy * dy),
|
|
35957
|
+
finalAngle = Math.atan2(dy, dx) + distance * strength * time * .02,
|
|
35958
|
+
sourceX = Math.round(centerX + distance * Math.cos(finalAngle)),
|
|
35959
|
+
sourceY = Math.round(centerY + distance * Math.sin(finalAngle)),
|
|
35960
|
+
targetIndex = 4 * (y * width + x);
|
|
35961
|
+
if (sourceX >= 0 && sourceX < width && sourceY >= 0 && sourceY < height) {
|
|
35962
|
+
const sourceIndex = 4 * (sourceY * width + sourceX);
|
|
35963
|
+
result[targetIndex] = data[sourceIndex], result[targetIndex + 1] = data[sourceIndex + 1], result[targetIndex + 2] = data[sourceIndex + 2], result[targetIndex + 3] = data[sourceIndex + 3];
|
|
35964
|
+
} else result[targetIndex + 3] = 0;
|
|
35965
|
+
}
|
|
35966
|
+
return new ImageData(result, width, height);
|
|
35967
|
+
}
|
|
35968
|
+
afterStageRender(stage, canvas) {
|
|
35969
|
+
return this.distortionConfig.strength <= 0 ? canvas : super.afterStageRender(stage, canvas);
|
|
35970
|
+
}
|
|
35971
|
+
}
|
|
35972
|
+
|
|
35973
|
+
class Particle extends HybridEffectBase {
|
|
35974
|
+
constructor(from, to, duration, easing, params) {
|
|
35975
|
+
var _a, _b, _c, _d, _e;
|
|
35976
|
+
super(from, to, duration, easing, params), this.particles = [], this.positionBuffer = null, this.colorBuffer = null, this.particleConfig = {
|
|
35977
|
+
effectType: (null === (_a = null == params ? void 0 : params.options) || void 0 === _a ? void 0 : _a.effectType) || "gravity",
|
|
35978
|
+
count: (null === (_b = null == params ? void 0 : params.options) || void 0 === _b ? void 0 : _b.count) || 4e3,
|
|
35979
|
+
size: (null === (_c = null == params ? void 0 : params.options) || void 0 === _c ? void 0 : _c.size) || 20,
|
|
35980
|
+
strength: (null === (_d = null == params ? void 0 : params.options) || void 0 === _d ? void 0 : _d.strength) || 1.5,
|
|
35981
|
+
useWebGL: void 0 === (null === (_e = null == params ? void 0 : params.options) || void 0 === _e ? void 0 : _e.useWebGL) || params.options.useWebGL
|
|
35982
|
+
};
|
|
35983
|
+
}
|
|
35984
|
+
getShaderSources() {
|
|
35985
|
+
return {
|
|
35986
|
+
vertex: "\n attribute vec2 a_position;\n attribute vec4 a_color;\n attribute float a_size;\n\n uniform vec2 u_resolution;\n uniform float u_time;\n uniform float u_forceStrength;\n uniform int u_effectType;\n\n varying vec4 v_color;\n\n void main() {\n // 将像素坐标转换为剪辑空间坐标\n vec2 clipSpace = ((a_position / u_resolution) * 2.0) - 1.0;\n clipSpace.y = -clipSpace.y; // 翻转Y轴\n\n gl_Position = vec4(clipSpace, 0.0, 1.0);\n gl_PointSize = a_size;\n v_color = a_color;\n }\n ",
|
|
35987
|
+
fragment: "\n precision mediump float;\n varying vec4 v_color;\n\n void main() {\n // 创建圆形粒子\n vec2 coord = gl_PointCoord - vec2(0.5);\n float distance = length(coord);\n\n if (distance > 0.5) {\n discard;\n }\n\n // 保持原始颜色,只调整透明度渐变\n gl_FragColor = vec4(v_color.rgb, v_color.a);\n }\n "
|
|
35988
|
+
};
|
|
35989
|
+
}
|
|
35990
|
+
applyWebGLEffect(canvas) {
|
|
35991
|
+
if (!this.gl || !this.program || !this.webglCanvas) return null;
|
|
35992
|
+
this.setupWebGLState(canvas), 0 === this.particles.length && this.extractParticles(canvas), this.updateParticles(canvas);
|
|
35993
|
+
const gl = this.gl;
|
|
35994
|
+
return gl.enable(gl.BLEND), gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA), gl.useProgram(this.program), this.prepareAndDrawParticles(gl), this.webglCanvas;
|
|
35995
|
+
}
|
|
35996
|
+
applyCanvas2DEffect(canvas) {
|
|
35997
|
+
const output = this.createOutputCanvas(canvas);
|
|
35998
|
+
if (!output) return null;
|
|
35999
|
+
const {
|
|
36000
|
+
canvas: outputCanvas,
|
|
36001
|
+
ctx: ctx
|
|
36002
|
+
} = output,
|
|
36003
|
+
progress = this.currentAnimationRatio;
|
|
36004
|
+
switch (this.particleConfig.effectType) {
|
|
36005
|
+
case "explode":
|
|
36006
|
+
this.applyCanvas2DExplode(ctx, canvas, progress);
|
|
36007
|
+
break;
|
|
36008
|
+
case "gravity":
|
|
36009
|
+
this.applyCanvas2DGravity(ctx, canvas, progress);
|
|
36010
|
+
break;
|
|
36011
|
+
case "vortex":
|
|
36012
|
+
this.applyCanvas2DVortex(ctx, canvas, progress);
|
|
36013
|
+
break;
|
|
36014
|
+
default:
|
|
36015
|
+
ctx.globalAlpha = Math.max(0, 1 - progress), ctx.drawImage(canvas, 0, 0);
|
|
36016
|
+
}
|
|
36017
|
+
return outputCanvas;
|
|
36018
|
+
}
|
|
36019
|
+
extractParticles(canvas) {
|
|
36020
|
+
const tempCanvas = ImageProcessUtils.createTempCanvas(canvas.width, canvas.height, 1),
|
|
36021
|
+
tempCtx = tempCanvas.getContext("2d");
|
|
36022
|
+
if (!tempCtx) return;
|
|
36023
|
+
tempCtx.drawImage(canvas, 0, 0, tempCanvas.width, tempCanvas.height);
|
|
36024
|
+
const data = tempCtx.getImageData(0, 0, tempCanvas.width, tempCanvas.height).data;
|
|
36025
|
+
this.particles = [];
|
|
36026
|
+
const step = Math.max(1, Math.floor(Math.sqrt(tempCanvas.width * tempCanvas.height / (1.5 * this.particleConfig.count))));
|
|
36027
|
+
for (let y = 0; y < tempCanvas.height; y += step) for (let x = 0; x < tempCanvas.width; x += step) {
|
|
36028
|
+
const index = 4 * (y * tempCanvas.width + x),
|
|
36029
|
+
r = data[index],
|
|
36030
|
+
g = data[index + 1],
|
|
36031
|
+
b = data[index + 2],
|
|
36032
|
+
a = data[index + 3];
|
|
36033
|
+
if (a > 5) {
|
|
36034
|
+
const realX = x / tempCanvas.width * canvas.width,
|
|
36035
|
+
realY = y / tempCanvas.height * canvas.height,
|
|
36036
|
+
particle = {
|
|
36037
|
+
x: realX,
|
|
36038
|
+
y: realY,
|
|
36039
|
+
originX: realX,
|
|
36040
|
+
originY: realY,
|
|
36041
|
+
vx: 0,
|
|
36042
|
+
vy: 0,
|
|
36043
|
+
r: r / 255,
|
|
36044
|
+
g: g / 255,
|
|
36045
|
+
b: b / 255,
|
|
36046
|
+
a: Math.max(.6, a / 255),
|
|
36047
|
+
life: 1,
|
|
36048
|
+
size: this.particleConfig.size * (1 + .5 * Math.random())
|
|
36049
|
+
};
|
|
36050
|
+
this.particles.push(particle);
|
|
36051
|
+
}
|
|
36052
|
+
}
|
|
36053
|
+
}
|
|
36054
|
+
updateParticles(canvas) {
|
|
36055
|
+
const centerX = canvas.width / 2,
|
|
36056
|
+
centerY = canvas.height / 2,
|
|
36057
|
+
progress = this.currentAnimationRatio,
|
|
36058
|
+
duration = this.getDurationFromParent(),
|
|
36059
|
+
isShortAnimation = duration < 2e3,
|
|
36060
|
+
timeMultiplier = isShortAnimation ? Math.max(1.5, 3e3 / duration) : 1,
|
|
36061
|
+
intensityBoost = isShortAnimation ? Math.min(2, 2e3 / duration) : 1;
|
|
36062
|
+
this.particles.forEach(particle => {
|
|
36063
|
+
const dx = particle.x - centerX,
|
|
36064
|
+
dy = particle.y - centerY,
|
|
36065
|
+
distance = Math.sqrt(dx * dx + dy * dy),
|
|
36066
|
+
angle = Math.atan2(dy, dx);
|
|
36067
|
+
this.applyParticleForces(particle, angle, distance, progress, intensityBoost, canvas), this.updateParticleProperties(particle, progress, isShortAnimation, timeMultiplier, intensityBoost);
|
|
36068
|
+
});
|
|
36069
|
+
}
|
|
36070
|
+
applyParticleForces(particle, angle, distance, progress, intensityBoost, canvas) {
|
|
36071
|
+
const time = this.getAnimationTime();
|
|
36072
|
+
switch (this.particleConfig.effectType) {
|
|
36073
|
+
case "explode":
|
|
36074
|
+
const explodeIntensity = progress * this.particleConfig.strength * intensityBoost * 5;
|
|
36075
|
+
particle.vx += Math.cos(angle) * explodeIntensity, particle.vy += Math.sin(angle) * explodeIntensity;
|
|
36076
|
+
break;
|
|
36077
|
+
case "gravity":
|
|
36078
|
+
this.applyGravityEffect(particle, progress, intensityBoost, canvas, time);
|
|
36079
|
+
break;
|
|
36080
|
+
case "vortex":
|
|
36081
|
+
this.applyVortexEffect(particle, progress, intensityBoost, canvas, angle, distance);
|
|
36082
|
+
}
|
|
36083
|
+
}
|
|
36084
|
+
applyGravityEffect(particle, progress, intensityBoost, canvas, time) {
|
|
36085
|
+
const gravityThreshold = (particle.originX + .7 * particle.originY) / (canvas.width + canvas.height) * .8;
|
|
36086
|
+
if (progress > gravityThreshold) {
|
|
36087
|
+
const gravityProgress = (progress - gravityThreshold) / (1 - gravityThreshold),
|
|
36088
|
+
gravityForce = this.particleConfig.strength * gravityProgress * gravityProgress * 12 * intensityBoost;
|
|
36089
|
+
particle.vy += gravityForce;
|
|
36090
|
+
const turbulence = Math.sin(3 * time + .02 * particle.originX) * Math.cos(2 * time + .015 * particle.originY);
|
|
36091
|
+
particle.vx += turbulence * this.particleConfig.strength * 2 * intensityBoost;
|
|
36092
|
+
}
|
|
36093
|
+
}
|
|
36094
|
+
applyVortexEffect(particle, progress, intensityBoost, canvas, angle, distance) {
|
|
36095
|
+
const centerX = canvas.width / 2,
|
|
36096
|
+
centerY = canvas.height / 2,
|
|
36097
|
+
spiralAngle = angle + progress * Math.PI * .8,
|
|
36098
|
+
targetRadius = distance + progress * Math.max(canvas.width, canvas.height) * .7 * 1.8,
|
|
36099
|
+
targetX = centerX + Math.cos(spiralAngle) * targetRadius,
|
|
36100
|
+
targetY = centerY + Math.sin(spiralAngle) * targetRadius,
|
|
36101
|
+
baseForce = progress * this.particleConfig.strength * .08 * intensityBoost;
|
|
36102
|
+
particle.vx += (targetX - particle.x) * baseForce, particle.vy += (targetY - particle.y) * baseForce;
|
|
36103
|
+
}
|
|
36104
|
+
updateParticleProperties(particle, progress, isShortAnimation, timeMultiplier, intensityBoost) {
|
|
36105
|
+
const dragCoeff = isShortAnimation ? .99 : .98;
|
|
36106
|
+
if (particle.vx *= dragCoeff, particle.vy *= dragCoeff, particle.x += particle.vx, particle.y += particle.vy, isShortAnimation) {
|
|
36107
|
+
const lifeDecayRate = Math.max(.1, .5 / timeMultiplier);
|
|
36108
|
+
particle.life = Math.max(0, 1 - progress * lifeDecayRate), particle.a = Math.max(.2, particle.life * Math.min(1, 1.2 * particle.a)), particle.size = Math.max(.7 * this.particleConfig.size, this.particleConfig.size * (.5 + .5 * particle.life));
|
|
36109
|
+
} else particle.life = Math.max(0, 1 - .2 * progress), particle.a = Math.max(.1, particle.life * Math.min(1, 1.5 * particle.a)), particle.size = Math.max(.5 * this.particleConfig.size, this.particleConfig.size * (.3 + .7 * particle.life));
|
|
36110
|
+
}
|
|
36111
|
+
prepareAndDrawParticles(gl) {
|
|
36112
|
+
const positions = new Float32Array(2 * this.particles.length),
|
|
36113
|
+
colors = new Float32Array(4 * this.particles.length),
|
|
36114
|
+
sizes = new Float32Array(this.particles.length);
|
|
36115
|
+
this.particles.forEach((particle, i) => {
|
|
36116
|
+
positions[2 * i] = particle.x, positions[2 * i + 1] = particle.y, colors[4 * i] = particle.r, colors[4 * i + 1] = particle.g, colors[4 * i + 2] = particle.b, colors[4 * i + 3] = Math.max(.1, particle.a), sizes[i] = Math.max(6, 1.5 * particle.size);
|
|
36117
|
+
}), this.updateParticleBuffers(gl, positions, colors, sizes), this.setParticleUniforms(gl), gl.drawArrays(gl.POINTS, 0, this.particles.length), this.cleanupTempBuffers(gl);
|
|
36118
|
+
}
|
|
36119
|
+
updateParticleBuffers(gl, positions, colors, sizes) {
|
|
36120
|
+
this.positionBuffer || (this.positionBuffer = gl.createBuffer()), gl.bindBuffer(gl.ARRAY_BUFFER, this.positionBuffer), gl.bufferData(gl.ARRAY_BUFFER, positions, gl.DYNAMIC_DRAW);
|
|
36121
|
+
const positionLocation = gl.getAttribLocation(this.program, "a_position");
|
|
36122
|
+
gl.enableVertexAttribArray(positionLocation), gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, !1, 0, 0), this.colorBuffer || (this.colorBuffer = gl.createBuffer()), gl.bindBuffer(gl.ARRAY_BUFFER, this.colorBuffer), gl.bufferData(gl.ARRAY_BUFFER, colors, gl.DYNAMIC_DRAW);
|
|
36123
|
+
const colorLocation = gl.getAttribLocation(this.program, "a_color");
|
|
36124
|
+
gl.enableVertexAttribArray(colorLocation), gl.vertexAttribPointer(colorLocation, 4, gl.FLOAT, !1, 0, 0);
|
|
36125
|
+
const sizeBuffer = gl.createBuffer();
|
|
36126
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, sizeBuffer), gl.bufferData(gl.ARRAY_BUFFER, sizes, gl.DYNAMIC_DRAW);
|
|
36127
|
+
const sizeLocation = gl.getAttribLocation(this.program, "a_size");
|
|
36128
|
+
gl.enableVertexAttribArray(sizeLocation), gl.vertexAttribPointer(sizeLocation, 1, gl.FLOAT, !1, 0, 0), this._tempSizeBuffer = sizeBuffer;
|
|
36129
|
+
}
|
|
36130
|
+
setParticleUniforms(gl) {
|
|
36131
|
+
const resolutionLocation = gl.getUniformLocation(this.program, "u_resolution"),
|
|
36132
|
+
timeLocation = gl.getUniformLocation(this.program, "u_time"),
|
|
36133
|
+
forceStrengthLocation = gl.getUniformLocation(this.program, "u_forceStrength"),
|
|
36134
|
+
effectTypeLocation = gl.getUniformLocation(this.program, "u_effectType");
|
|
36135
|
+
gl.uniform2f(resolutionLocation, this.webglCanvas.width, this.webglCanvas.height), gl.uniform1f(timeLocation, this.getAnimationTime()), gl.uniform1f(forceStrengthLocation, this.particleConfig.strength);
|
|
36136
|
+
gl.uniform1i(effectTypeLocation, {
|
|
36137
|
+
explode: 0,
|
|
36138
|
+
vortex: 1,
|
|
36139
|
+
gravity: 2
|
|
36140
|
+
}[this.particleConfig.effectType] || 0);
|
|
36141
|
+
}
|
|
36142
|
+
cleanupTempBuffers(gl) {
|
|
36143
|
+
const tempSizeBuffer = this._tempSizeBuffer;
|
|
36144
|
+
tempSizeBuffer && (gl.deleteBuffer(tempSizeBuffer), delete this._tempSizeBuffer);
|
|
36145
|
+
}
|
|
36146
|
+
applyCanvas2DExplode(ctx, canvas, progress) {
|
|
36147
|
+
const centerX = canvas.width / 2,
|
|
36148
|
+
centerY = canvas.height / 2;
|
|
36149
|
+
ctx.save(), ctx.globalAlpha = Math.max(0, 1 - progress), ctx.translate(centerX, centerY);
|
|
36150
|
+
const scale = 1 + .5 * progress;
|
|
36151
|
+
ctx.scale(scale, scale), ctx.translate(-centerX, -centerY), ctx.drawImage(canvas, 0, 0), ctx.restore();
|
|
36152
|
+
}
|
|
36153
|
+
applyCanvas2DGravity(ctx, canvas, progress) {
|
|
36154
|
+
ctx.save(), ctx.globalAlpha = Math.max(0, 1 - progress);
|
|
36155
|
+
const offsetY = progress * canvas.height * .3;
|
|
36156
|
+
ctx.drawImage(canvas, 0, offsetY), ctx.restore();
|
|
36157
|
+
}
|
|
36158
|
+
applyCanvas2DVortex(ctx, canvas, progress) {
|
|
36159
|
+
const centerX = canvas.width / 2,
|
|
36160
|
+
centerY = canvas.height / 2;
|
|
36161
|
+
ctx.save(), ctx.globalAlpha = Math.max(0, 1 - progress), ctx.translate(centerX, centerY), ctx.rotate(progress * Math.PI * 2), ctx.translate(-centerX, -centerY), ctx.drawImage(canvas, 0, 0), ctx.restore();
|
|
36162
|
+
}
|
|
36163
|
+
}
|
|
36164
|
+
|
|
36165
|
+
class Glitch extends Canvas2DEffectBase {
|
|
36166
|
+
constructor(from, to, duration, easing, params) {
|
|
36167
|
+
var _a, _b;
|
|
36168
|
+
super(from, to, duration, easing, params), this.glitchConfig = {
|
|
36169
|
+
effectType: (null === (_a = null == params ? void 0 : params.options) || void 0 === _a ? void 0 : _a.effectType) || "rgb-shift",
|
|
36170
|
+
intensity: void 0 !== (null === (_b = null == params ? void 0 : params.options) || void 0 === _b ? void 0 : _b.intensity) ? params.options.intensity : .5
|
|
36171
|
+
};
|
|
36172
|
+
}
|
|
36173
|
+
applyCanvas2DEffect(canvas) {
|
|
36174
|
+
if (this.glitchConfig.intensity <= 0) {
|
|
36175
|
+
const outputCanvas = this.createOutputCanvas(canvas);
|
|
36176
|
+
return outputCanvas ? outputCanvas.canvas : null;
|
|
36177
|
+
}
|
|
36178
|
+
try {
|
|
36179
|
+
switch (this.glitchConfig.effectType) {
|
|
36180
|
+
case "rgb-shift":
|
|
36181
|
+
default:
|
|
36182
|
+
return this.applyRGBShiftGlitch(canvas);
|
|
36183
|
+
case "digital-distortion":
|
|
36184
|
+
return this.applyDigitalDistortionGlitch(canvas);
|
|
36185
|
+
case "scan-lines":
|
|
36186
|
+
return this.applyScanLineGlitch(canvas);
|
|
36187
|
+
case "data-corruption":
|
|
36188
|
+
return this.applyDataCorruptionGlitch(canvas);
|
|
36189
|
+
}
|
|
36190
|
+
} catch (error) {
|
|
36191
|
+
return console.warn("Glitch effect failed:", error), null;
|
|
36192
|
+
}
|
|
36193
|
+
}
|
|
36194
|
+
applyRGBShiftGlitch(canvas) {
|
|
36195
|
+
const outputCanvas = this.createOutputCanvas(canvas);
|
|
36196
|
+
if (!outputCanvas) return null;
|
|
36197
|
+
const {
|
|
36198
|
+
ctx: ctx
|
|
36199
|
+
} = outputCanvas;
|
|
36200
|
+
try {
|
|
36201
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
36202
|
+
const dynamicIntensity = ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime()),
|
|
36203
|
+
maxOffset = Math.floor(20 * dynamicIntensity),
|
|
36204
|
+
redOffset = this.generateRandomOffset(maxOffset),
|
|
36205
|
+
greenOffset = this.generateRandomOffset(maxOffset, .3),
|
|
36206
|
+
blueOffset = this.generateRandomOffset(-maxOffset),
|
|
36207
|
+
tempCanvas = ImageProcessUtils.createTempCanvas(canvas.width, canvas.height),
|
|
36208
|
+
tempCtx = tempCanvas.getContext("2d");
|
|
36209
|
+
tempCtx.drawImage(canvas, 0, 0);
|
|
36210
|
+
const originalImageData = tempCtx.getImageData(0, 0, canvas.width, canvas.height),
|
|
36211
|
+
redChannelData = ImageProcessUtils.extractChannel(originalImageData, 0),
|
|
36212
|
+
greenChannelData = ImageProcessUtils.extractChannel(originalImageData, 1),
|
|
36213
|
+
blueChannelData = ImageProcessUtils.extractChannel(originalImageData, 2);
|
|
36214
|
+
return ctx.globalCompositeOperation = "screen", tempCtx.clearRect(0, 0, canvas.width, canvas.height), tempCtx.putImageData(redChannelData, 0, 0), ctx.drawImage(tempCanvas, redOffset.x, redOffset.y), tempCtx.clearRect(0, 0, canvas.width, canvas.height), tempCtx.putImageData(greenChannelData, 0, 0), ctx.drawImage(tempCanvas, greenOffset.x, greenOffset.y), tempCtx.clearRect(0, 0, canvas.width, canvas.height), tempCtx.putImageData(blueChannelData, 0, 0), ctx.drawImage(tempCanvas, blueOffset.x, blueOffset.y), ctx.globalCompositeOperation = "source-over", outputCanvas.canvas;
|
|
36215
|
+
} catch (error) {
|
|
36216
|
+
return console.warn("RGB shift glitch failed:", error), null;
|
|
36217
|
+
}
|
|
36218
|
+
}
|
|
36219
|
+
applyDigitalDistortionGlitch(canvas) {
|
|
36220
|
+
const outputCanvas = this.createOutputCanvas(canvas);
|
|
36221
|
+
if (!outputCanvas) return null;
|
|
36222
|
+
const {
|
|
36223
|
+
ctx: ctx
|
|
36224
|
+
} = outputCanvas;
|
|
36225
|
+
try {
|
|
36226
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height),
|
|
36227
|
+
dynamicIntensity = ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime()),
|
|
36228
|
+
distortedImageData = this.processDigitalDistortion(imageData, dynamicIntensity);
|
|
36229
|
+
return ctx.clearRect(0, 0, canvas.width, canvas.height), ctx.putImageData(distortedImageData, 0, 0), outputCanvas.canvas;
|
|
36230
|
+
} catch (error) {
|
|
36231
|
+
return console.warn("Digital distortion glitch failed:", error), null;
|
|
36232
|
+
}
|
|
36233
|
+
}
|
|
36234
|
+
applyScanLineGlitch(canvas) {
|
|
36235
|
+
const outputCanvas = this.createOutputCanvas(canvas);
|
|
36236
|
+
if (!outputCanvas) return null;
|
|
36237
|
+
const {
|
|
36238
|
+
ctx: ctx
|
|
36239
|
+
} = outputCanvas;
|
|
36240
|
+
try {
|
|
36241
|
+
const dynamicIntensity = ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime()),
|
|
36242
|
+
lineSpacing = Math.max(2, Math.floor(10 - 8 * dynamicIntensity));
|
|
36243
|
+
ctx.globalCompositeOperation = "multiply";
|
|
36244
|
+
for (let y = 0; y < canvas.height; y += lineSpacing) if (Math.random() < dynamicIntensity) {
|
|
36245
|
+
const opacity = .1 + .4 * dynamicIntensity;
|
|
36246
|
+
ctx.fillStyle = `rgba(0, 0, 0, ${opacity})`, ctx.fillRect(0, y, canvas.width, 1);
|
|
36247
|
+
}
|
|
36248
|
+
ctx.globalCompositeOperation = "screen";
|
|
36249
|
+
const brightLineCount = Math.floor(20 * dynamicIntensity);
|
|
36250
|
+
for (let i = 0; i < brightLineCount; i++) {
|
|
36251
|
+
const y = Math.random() * canvas.height,
|
|
36252
|
+
opacity = .3 * dynamicIntensity;
|
|
36253
|
+
ctx.fillStyle = `rgba(255, 255, 255, ${opacity})`, ctx.fillRect(0, Math.floor(y), canvas.width, 1);
|
|
36254
|
+
}
|
|
36255
|
+
return ctx.globalCompositeOperation = "source-over", outputCanvas.canvas;
|
|
36256
|
+
} catch (error) {
|
|
36257
|
+
return console.warn("Scan line glitch failed:", error), null;
|
|
36258
|
+
}
|
|
36259
|
+
}
|
|
36260
|
+
applyDataCorruptionGlitch(canvas) {
|
|
36261
|
+
const outputCanvas = this.createOutputCanvas(canvas);
|
|
36262
|
+
if (!outputCanvas) return null;
|
|
36263
|
+
const {
|
|
36264
|
+
ctx: ctx
|
|
36265
|
+
} = outputCanvas;
|
|
36266
|
+
try {
|
|
36267
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height),
|
|
36268
|
+
dynamicIntensity = ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime()),
|
|
36269
|
+
corruptedImageData = this.processDataCorruption(imageData, dynamicIntensity);
|
|
36270
|
+
return ctx.clearRect(0, 0, canvas.width, canvas.height), ctx.putImageData(corruptedImageData, 0, 0), outputCanvas.canvas;
|
|
36271
|
+
} catch (error) {
|
|
36272
|
+
return console.warn("Data corruption glitch failed:", error), null;
|
|
36273
|
+
}
|
|
36274
|
+
}
|
|
36275
|
+
generateRandomOffset(maxOffset, scale = 1) {
|
|
36276
|
+
return {
|
|
36277
|
+
x: (Math.random() - .5) * maxOffset,
|
|
36278
|
+
y: (Math.random() - .5) * maxOffset * scale
|
|
36279
|
+
};
|
|
36280
|
+
}
|
|
36281
|
+
processDigitalDistortion(imageData, intensity) {
|
|
36282
|
+
const {
|
|
36283
|
+
data: data,
|
|
36284
|
+
width: width,
|
|
36285
|
+
height: height
|
|
36286
|
+
} = imageData,
|
|
36287
|
+
result = new Uint8ClampedArray(data),
|
|
36288
|
+
sliceCount = Math.floor(20 * intensity) + 5,
|
|
36289
|
+
sliceHeight = Math.floor(height / sliceCount);
|
|
36290
|
+
for (let i = 0; i < sliceCount; i++) if (Math.random() < intensity) {
|
|
36291
|
+
const y = i * sliceHeight,
|
|
36292
|
+
sliceEnd = Math.min(y + sliceHeight, height),
|
|
36293
|
+
offset = Math.floor((Math.random() - .5) * width * intensity * .1);
|
|
36294
|
+
this.shiftSliceHorizontal(result, width, height, y, sliceEnd, offset);
|
|
36295
|
+
}
|
|
36296
|
+
const noiseIntensity = .3 * intensity;
|
|
36297
|
+
for (let i = 0; i < data.length; i += 4) Math.random() < noiseIntensity && (result[i] = 255 * Math.random(), result[i + 1] = 255 * Math.random(), result[i + 2] = 255 * Math.random());
|
|
36298
|
+
return new ImageData(result, width, height);
|
|
36299
|
+
}
|
|
36300
|
+
shiftSliceHorizontal(data, width, height, startY, endY, offset) {
|
|
36301
|
+
const tempRow = new Uint8ClampedArray(4 * width);
|
|
36302
|
+
for (let y = startY; y < endY; y++) {
|
|
36303
|
+
const rowStart = y * width * 4;
|
|
36304
|
+
for (let x = 0; x < 4 * width; x++) tempRow[x] = data[rowStart + x];
|
|
36305
|
+
for (let x = 0; x < width; x++) {
|
|
36306
|
+
const targetIndex = rowStart + 4 * x,
|
|
36307
|
+
sourceIndex = 4 * ((x - offset + width) % width);
|
|
36308
|
+
data[targetIndex] = tempRow[sourceIndex], data[targetIndex + 1] = tempRow[sourceIndex + 1], data[targetIndex + 2] = tempRow[sourceIndex + 2], data[targetIndex + 3] = tempRow[sourceIndex + 3];
|
|
36309
|
+
}
|
|
36310
|
+
}
|
|
36311
|
+
}
|
|
36312
|
+
processDataCorruption(imageData, intensity) {
|
|
36313
|
+
const {
|
|
36314
|
+
data: data,
|
|
36315
|
+
width: width,
|
|
36316
|
+
height: height
|
|
36317
|
+
} = imageData,
|
|
36318
|
+
result = new Uint8ClampedArray(data),
|
|
36319
|
+
stripeCount = Math.floor(15 * intensity) + 5;
|
|
36320
|
+
for (let i = 0; i < stripeCount; i++) if (Math.random() < intensity) {
|
|
36321
|
+
const x = Math.floor(Math.random() * width),
|
|
36322
|
+
stripeWidth = Math.floor(5 * Math.random()) + 1,
|
|
36323
|
+
color = Math.random() < .5 ? 0 : 255;
|
|
36324
|
+
for (let y = 0; y < height; y++) for (let dx = 0; dx < stripeWidth && x + dx < width; dx++) {
|
|
36325
|
+
const index = 4 * (y * width + x + dx);
|
|
36326
|
+
result[index] = color, result[index + 1] = color, result[index + 2] = color;
|
|
36327
|
+
}
|
|
36328
|
+
}
|
|
36329
|
+
const corruptionCount = Math.floor(20 * intensity);
|
|
36330
|
+
for (let i = 0; i < corruptionCount; i++) {
|
|
36331
|
+
const blockX = Math.floor(Math.random() * width),
|
|
36332
|
+
blockY = Math.floor(Math.random() * height),
|
|
36333
|
+
blockW = Math.floor(20 * Math.random()) + 5,
|
|
36334
|
+
blockH = Math.floor(10 * Math.random()) + 2;
|
|
36335
|
+
this.corruptBlock(result, width, height, blockX, blockY, blockW, blockH);
|
|
36336
|
+
}
|
|
36337
|
+
return new ImageData(result, width, height);
|
|
36338
|
+
}
|
|
36339
|
+
corruptBlock(data, width, height, x, y, w, h) {
|
|
36340
|
+
for (let dy = 0; dy < h && y + dy < height; dy++) for (let dx = 0; dx < w && x + dx < width; dx++) {
|
|
36341
|
+
const index = 4 * ((y + dy) * width + (x + dx));
|
|
36342
|
+
Math.random() < .7 && (data[index] = 255 * Math.random(), data[index + 1] = 255 * Math.random(), data[index + 2] = 255 * Math.random());
|
|
36343
|
+
}
|
|
36344
|
+
}
|
|
36345
|
+
}
|
|
36346
|
+
|
|
36347
|
+
class GaussianBlur extends AStageAnimate {
|
|
36348
|
+
constructor(from, to, duration, easing, params) {
|
|
36349
|
+
var _a, _b;
|
|
36350
|
+
super(from, to, duration, easing, params), this.blurConfig = {
|
|
36351
|
+
blurRadius: (null === (_a = null == params ? void 0 : params.options) || void 0 === _a ? void 0 : _a.blurRadius) || 8,
|
|
36352
|
+
useOptimizedBlur: void 0 === (null === (_b = null == params ? void 0 : params.options) || void 0 === _b ? void 0 : _b.useOptimizedBlur) || params.options.useOptimizedBlur
|
|
36353
|
+
};
|
|
36354
|
+
}
|
|
36355
|
+
applyCSSBlur(canvas, radius) {
|
|
36356
|
+
const c = vglobal.createCanvas({
|
|
36357
|
+
width: canvas.width,
|
|
36358
|
+
height: canvas.height,
|
|
36359
|
+
dpr: vglobal.devicePixelRatio
|
|
36360
|
+
}),
|
|
36361
|
+
ctx = c.getContext("2d");
|
|
36362
|
+
return ctx ? (ctx.filter = `blur(${radius}px)`, ctx.drawImage(canvas, 0, 0), ctx.filter = "none", c) : canvas;
|
|
36363
|
+
}
|
|
36364
|
+
applyDownsampleBlur(imageData, radius) {
|
|
36365
|
+
const {
|
|
36366
|
+
width: width,
|
|
36367
|
+
height: height
|
|
36368
|
+
} = imageData,
|
|
36369
|
+
downsample = Math.max(1, Math.floor(radius / 2)),
|
|
36370
|
+
smallWidth = Math.floor(width / downsample),
|
|
36371
|
+
smallHeight = Math.floor(height / downsample),
|
|
36372
|
+
tempCanvas = vglobal.createCanvas({
|
|
36373
|
+
width: smallWidth,
|
|
36374
|
+
height: smallHeight,
|
|
36375
|
+
dpr: 1
|
|
36376
|
+
}),
|
|
36377
|
+
tempCtx = tempCanvas.getContext("2d");
|
|
36378
|
+
if (!tempCtx) return imageData;
|
|
36379
|
+
const originalCanvas = vglobal.createCanvas({
|
|
36380
|
+
width: width,
|
|
36381
|
+
height: height,
|
|
36382
|
+
dpr: 1
|
|
36383
|
+
}),
|
|
36384
|
+
originalCtx = originalCanvas.getContext("2d");
|
|
36385
|
+
return originalCtx ? (originalCtx.putImageData(imageData, 0, 0), tempCtx.drawImage(originalCanvas, 0, 0, smallWidth, smallHeight), tempCtx.filter = `blur(${radius / downsample}px)`, tempCtx.drawImage(tempCanvas, 0, 0), tempCtx.filter = "none", originalCtx.clearRect(0, 0, width, height), originalCtx.drawImage(tempCanvas, 0, 0, width, height), originalCtx.getImageData(0, 0, width, height)) : imageData;
|
|
36386
|
+
}
|
|
36387
|
+
afterStageRender(stage, canvas) {
|
|
36388
|
+
if (this.blurConfig.blurRadius <= 0) return canvas;
|
|
36389
|
+
let result;
|
|
36390
|
+
if (this.blurConfig.useOptimizedBlur) result = this.applyCSSBlur(canvas, this.blurConfig.blurRadius);else {
|
|
36391
|
+
const c = vglobal.createCanvas({
|
|
36392
|
+
width: canvas.width,
|
|
36393
|
+
height: canvas.height,
|
|
36394
|
+
dpr: vglobal.devicePixelRatio
|
|
36395
|
+
}),
|
|
36396
|
+
ctx = c.getContext("2d");
|
|
36397
|
+
if (!ctx) return !1;
|
|
36398
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height), ctx.drawImage(canvas, 0, 0);
|
|
36399
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height),
|
|
36400
|
+
blurredImageData = this.applyDownsampleBlur(imageData, this.blurConfig.blurRadius);
|
|
36401
|
+
ctx.putImageData(blurredImageData, 0, 0), result = c;
|
|
36402
|
+
}
|
|
36403
|
+
const ctx = result.getContext("2d");
|
|
36404
|
+
return ctx && (ctx.globalCompositeOperation = "overlay", ctx.fillStyle = "rgba(255, 255, 255, 0.1)", ctx.fillRect(0, 0, result.width, result.height), ctx.globalCompositeOperation = "source-over"), result;
|
|
36405
|
+
}
|
|
36406
|
+
}
|
|
36407
|
+
|
|
36408
|
+
class Pixelation extends DisappearAnimateBase {
|
|
36409
|
+
constructor(from, to, duration, easing, params) {
|
|
36410
|
+
var _a, _b;
|
|
36411
|
+
super(from, to, duration, easing, params), this.pixelationConfig = {
|
|
36412
|
+
maxPixelSize: (null === (_a = null == params ? void 0 : params.options) || void 0 === _a ? void 0 : _a.maxPixelSize) || 20,
|
|
36413
|
+
method: (null === (_b = null == params ? void 0 : params.options) || void 0 === _b ? void 0 : _b.method) || "out"
|
|
36414
|
+
};
|
|
36415
|
+
}
|
|
36416
|
+
applyDownsamplePixelation(canvas, pixelSize) {
|
|
36417
|
+
if (pixelSize <= 1) return canvas;
|
|
36418
|
+
const {
|
|
36419
|
+
width: width,
|
|
36420
|
+
height: height
|
|
36421
|
+
} = canvas,
|
|
36422
|
+
smallWidth = Math.ceil(width / pixelSize),
|
|
36423
|
+
smallHeight = Math.ceil(height / pixelSize),
|
|
36424
|
+
smallCanvas = vglobal.createCanvas({
|
|
36425
|
+
width: smallWidth,
|
|
36426
|
+
height: smallHeight,
|
|
36427
|
+
dpr: 1
|
|
36428
|
+
}),
|
|
36429
|
+
smallCtx = smallCanvas.getContext("2d");
|
|
36430
|
+
if (!smallCtx) return canvas;
|
|
36431
|
+
const outputCanvas = vglobal.createCanvas({
|
|
36432
|
+
width: width,
|
|
36433
|
+
height: height,
|
|
36434
|
+
dpr: vglobal.devicePixelRatio
|
|
36435
|
+
}),
|
|
36436
|
+
outputCtx = outputCanvas.getContext("2d");
|
|
36437
|
+
return outputCtx ? (smallCtx.imageSmoothingEnabled = !1, outputCtx.imageSmoothingEnabled = !1, smallCtx.drawImage(canvas, 0, 0, smallWidth, smallHeight), outputCtx.drawImage(smallCanvas, 0, 0, width, height), outputCanvas) : canvas;
|
|
36438
|
+
}
|
|
36439
|
+
updateAnimationProgress() {
|
|
36440
|
+
if ("in" === this.pixelationConfig.method) {
|
|
36441
|
+
return this.pixelationConfig.maxPixelSize - this.currentAnimationRatio * (this.pixelationConfig.maxPixelSize - 1);
|
|
36442
|
+
}
|
|
36443
|
+
return 1 + this.currentAnimationRatio * (this.pixelationConfig.maxPixelSize - 1);
|
|
36444
|
+
}
|
|
36445
|
+
afterStageRender(stage, canvas) {
|
|
36446
|
+
const currentPixelSize = this.updateAnimationProgress();
|
|
36447
|
+
if (currentPixelSize <= 1) return canvas;
|
|
36448
|
+
return this.applyDownsamplePixelation(canvas, currentPixelSize);
|
|
36449
|
+
}
|
|
36450
|
+
}
|
|
36451
|
+
|
|
35152
36452
|
const registerCustomAnimate = () => {
|
|
35153
|
-
AnimateExecutor.registerBuiltInAnimate("increaseCount", IncreaseCount), AnimateExecutor.registerBuiltInAnimate("fromTo", FromTo), AnimateExecutor.registerBuiltInAnimate("scaleIn", ScaleIn), AnimateExecutor.registerBuiltInAnimate("scaleOut", ScaleOut), AnimateExecutor.registerBuiltInAnimate("growHeightIn", GrowHeightIn), AnimateExecutor.registerBuiltInAnimate("growHeightOut", GrowHeightOut), AnimateExecutor.registerBuiltInAnimate("growWidthIn", GrowWidthIn), AnimateExecutor.registerBuiltInAnimate("growWidthOut", GrowWidthOut), AnimateExecutor.registerBuiltInAnimate("growCenterIn", GrowCenterIn), AnimateExecutor.registerBuiltInAnimate("growCenterOut", GrowCenterOut), AnimateExecutor.registerBuiltInAnimate("clipIn", ClipIn), AnimateExecutor.registerBuiltInAnimate("clipOut", ClipOut), AnimateExecutor.registerBuiltInAnimate("fadeIn", FadeIn), AnimateExecutor.registerBuiltInAnimate("fadeOut", FadeOut), AnimateExecutor.registerBuiltInAnimate("growPointsIn", GrowPointsIn), AnimateExecutor.registerBuiltInAnimate("growPointsOut", GrowPointsOut), AnimateExecutor.registerBuiltInAnimate("growPointsXIn", GrowPointsXIn), AnimateExecutor.registerBuiltInAnimate("growPointsXOut", GrowPointsXOut), AnimateExecutor.registerBuiltInAnimate("growPointsYIn", GrowPointsYIn), AnimateExecutor.registerBuiltInAnimate("growPointsYOut", GrowPointsYOut), AnimateExecutor.registerBuiltInAnimate("growAngleIn", GrowAngleIn), AnimateExecutor.registerBuiltInAnimate("growAngleOut", GrowAngleOut), AnimateExecutor.registerBuiltInAnimate("growRadiusIn", GrowRadiusIn), AnimateExecutor.registerBuiltInAnimate("growRadiusOut", GrowRadiusOut), AnimateExecutor.registerBuiltInAnimate("moveIn", MoveIn), AnimateExecutor.registerBuiltInAnimate("moveOut", MoveOut), AnimateExecutor.registerBuiltInAnimate("rotateIn", RotateIn), AnimateExecutor.registerBuiltInAnimate("rotateOut", RotateOut), AnimateExecutor.registerBuiltInAnimate("update", Update), AnimateExecutor.registerBuiltInAnimate("state", State), AnimateExecutor.registerBuiltInAnimate("labelItemAppear", LabelItemAppear), AnimateExecutor.registerBuiltInAnimate("labelItemDisappear", LabelItemDisappear), AnimateExecutor.registerBuiltInAnimate("poptipAppear", PoptipAppear), AnimateExecutor.registerBuiltInAnimate("poptipDisappear", PoptipDisappear), AnimateExecutor.registerBuiltInAnimate("inputText", InputText), AnimateExecutor.registerBuiltInAnimate("inputRichText", InputRichText), AnimateExecutor.registerBuiltInAnimate("outputRichText", OutputRichText), AnimateExecutor.registerBuiltInAnimate("slideRichText", SlideRichText), AnimateExecutor.registerBuiltInAnimate("slideOutRichText", SlideOutRichText), AnimateExecutor.registerBuiltInAnimate("slideIn", SlideIn), AnimateExecutor.registerBuiltInAnimate("growIn", GrowIn), AnimateExecutor.registerBuiltInAnimate("spinIn", SpinIn), AnimateExecutor.registerBuiltInAnimate("moveScaleIn", MoveScaleIn), AnimateExecutor.registerBuiltInAnimate("moveRotateIn", MoveRotateIn), AnimateExecutor.registerBuiltInAnimate("strokeIn", StrokeIn), AnimateExecutor.registerBuiltInAnimate("slideOut", SlideOut), AnimateExecutor.registerBuiltInAnimate("growOut", GrowOut), AnimateExecutor.registerBuiltInAnimate("spinOut", SpinOut), AnimateExecutor.registerBuiltInAnimate("moveScaleOut", MoveScaleOut), AnimateExecutor.registerBuiltInAnimate("moveRotateOut", MoveRotateOut), AnimateExecutor.registerBuiltInAnimate("strokeOut", StrokeOut), AnimateExecutor.registerBuiltInAnimate("pulse", PulseAnimate), AnimateExecutor.registerBuiltInAnimate("MotionPath", MotionPath), AnimateExecutor.registerBuiltInAnimate("streamLight", StreamLight);
|
|
36453
|
+
AnimateExecutor.registerBuiltInAnimate("increaseCount", IncreaseCount), AnimateExecutor.registerBuiltInAnimate("fromTo", FromTo), AnimateExecutor.registerBuiltInAnimate("scaleIn", ScaleIn), AnimateExecutor.registerBuiltInAnimate("scaleOut", ScaleOut), AnimateExecutor.registerBuiltInAnimate("growHeightIn", GrowHeightIn), AnimateExecutor.registerBuiltInAnimate("growHeightOut", GrowHeightOut), AnimateExecutor.registerBuiltInAnimate("growWidthIn", GrowWidthIn), AnimateExecutor.registerBuiltInAnimate("growWidthOut", GrowWidthOut), AnimateExecutor.registerBuiltInAnimate("growCenterIn", GrowCenterIn), AnimateExecutor.registerBuiltInAnimate("growCenterOut", GrowCenterOut), AnimateExecutor.registerBuiltInAnimate("clipIn", ClipIn), AnimateExecutor.registerBuiltInAnimate("clipOut", ClipOut), AnimateExecutor.registerBuiltInAnimate("fadeIn", FadeIn), AnimateExecutor.registerBuiltInAnimate("fadeOut", FadeOut), AnimateExecutor.registerBuiltInAnimate("growPointsIn", GrowPointsIn), AnimateExecutor.registerBuiltInAnimate("growPointsOut", GrowPointsOut), AnimateExecutor.registerBuiltInAnimate("growPointsXIn", GrowPointsXIn), AnimateExecutor.registerBuiltInAnimate("growPointsXOut", GrowPointsXOut), AnimateExecutor.registerBuiltInAnimate("growPointsYIn", GrowPointsYIn), AnimateExecutor.registerBuiltInAnimate("growPointsYOut", GrowPointsYOut), AnimateExecutor.registerBuiltInAnimate("growAngleIn", GrowAngleIn), AnimateExecutor.registerBuiltInAnimate("growAngleOut", GrowAngleOut), AnimateExecutor.registerBuiltInAnimate("growRadiusIn", GrowRadiusIn), AnimateExecutor.registerBuiltInAnimate("growRadiusOut", GrowRadiusOut), AnimateExecutor.registerBuiltInAnimate("moveIn", MoveIn), AnimateExecutor.registerBuiltInAnimate("moveOut", MoveOut), AnimateExecutor.registerBuiltInAnimate("rotateIn", RotateIn), AnimateExecutor.registerBuiltInAnimate("rotateOut", RotateOut), AnimateExecutor.registerBuiltInAnimate("update", Update), AnimateExecutor.registerBuiltInAnimate("state", State), AnimateExecutor.registerBuiltInAnimate("labelItemAppear", LabelItemAppear), AnimateExecutor.registerBuiltInAnimate("labelItemDisappear", LabelItemDisappear), AnimateExecutor.registerBuiltInAnimate("poptipAppear", PoptipAppear), AnimateExecutor.registerBuiltInAnimate("poptipDisappear", PoptipDisappear), AnimateExecutor.registerBuiltInAnimate("inputText", InputText), AnimateExecutor.registerBuiltInAnimate("inputRichText", InputRichText), AnimateExecutor.registerBuiltInAnimate("outputRichText", OutputRichText), AnimateExecutor.registerBuiltInAnimate("slideRichText", SlideRichText), AnimateExecutor.registerBuiltInAnimate("slideOutRichText", SlideOutRichText), AnimateExecutor.registerBuiltInAnimate("slideIn", SlideIn), AnimateExecutor.registerBuiltInAnimate("growIn", GrowIn), AnimateExecutor.registerBuiltInAnimate("spinIn", SpinIn), AnimateExecutor.registerBuiltInAnimate("moveScaleIn", MoveScaleIn), AnimateExecutor.registerBuiltInAnimate("moveRotateIn", MoveRotateIn), AnimateExecutor.registerBuiltInAnimate("strokeIn", StrokeIn), AnimateExecutor.registerBuiltInAnimate("slideOut", SlideOut), AnimateExecutor.registerBuiltInAnimate("growOut", GrowOut), AnimateExecutor.registerBuiltInAnimate("spinOut", SpinOut), AnimateExecutor.registerBuiltInAnimate("moveScaleOut", MoveScaleOut), AnimateExecutor.registerBuiltInAnimate("moveRotateOut", MoveRotateOut), AnimateExecutor.registerBuiltInAnimate("strokeOut", StrokeOut), AnimateExecutor.registerBuiltInAnimate("pulse", PulseAnimate), AnimateExecutor.registerBuiltInAnimate("MotionPath", MotionPath), AnimateExecutor.registerBuiltInAnimate("streamLight", StreamLight), AnimateExecutor.registerBuiltInAnimate("dissolve", Dissolve), AnimateExecutor.registerBuiltInAnimate("grayscale", Grayscale), AnimateExecutor.registerBuiltInAnimate("distortion", Distortion), AnimateExecutor.registerBuiltInAnimate("particle", Particle), AnimateExecutor.registerBuiltInAnimate("glitch", Glitch), AnimateExecutor.registerBuiltInAnimate("gaussianBlur", GaussianBlur), AnimateExecutor.registerBuiltInAnimate("pixelation", Pixelation);
|
|
35154
36454
|
};
|
|
35155
36455
|
|
|
35156
|
-
const version = "1.0.
|
|
36456
|
+
const version = "1.0.13";
|
|
35157
36457
|
preLoadAllModule();
|
|
35158
36458
|
if (isBrowserEnv()) {
|
|
35159
36459
|
loadBrowserEnv(container);
|
|
@@ -35321,6 +36621,8 @@
|
|
|
35321
36621
|
exports.DefaultTimeline = DefaultTimeline;
|
|
35322
36622
|
exports.DefaultTransform = DefaultTransform;
|
|
35323
36623
|
exports.DirectionalLight = DirectionalLight;
|
|
36624
|
+
exports.Dissolve = Dissolve;
|
|
36625
|
+
exports.Distortion = Distortion;
|
|
35324
36626
|
exports.DragNDrop = DragNDrop;
|
|
35325
36627
|
exports.DrawContribution = DrawContribution;
|
|
35326
36628
|
exports.DrawItemInterceptor = DrawItemInterceptor;
|
|
@@ -35347,12 +36649,15 @@
|
|
|
35347
36649
|
exports.GLYPH_NUMBER_TYPE = GLYPH_NUMBER_TYPE;
|
|
35348
36650
|
exports.GRAPHIC_UPDATE_TAG_KEY = GRAPHIC_UPDATE_TAG_KEY;
|
|
35349
36651
|
exports.GROUP_NUMBER_TYPE = GROUP_NUMBER_TYPE;
|
|
36652
|
+
exports.GaussianBlur = GaussianBlur;
|
|
35350
36653
|
exports.Generator = Generator;
|
|
35351
36654
|
exports.Gesture = Gesture;
|
|
35352
36655
|
exports.GifImage = GifImage;
|
|
36656
|
+
exports.Glitch = Glitch;
|
|
35353
36657
|
exports.GlobalPickerService = GlobalPickerService;
|
|
35354
36658
|
exports.Glyph = Glyph;
|
|
35355
36659
|
exports.GlyphRender = GlyphRender;
|
|
36660
|
+
exports.GradientParser = GradientParser;
|
|
35356
36661
|
exports.Graphic = Graphic;
|
|
35357
36662
|
exports.GraphicCreator = GraphicCreator$1;
|
|
35358
36663
|
exports.GraphicPicker = GraphicPicker;
|
|
@@ -35360,6 +36665,7 @@
|
|
|
35360
36665
|
exports.GraphicService = GraphicService;
|
|
35361
36666
|
exports.GraphicStateExtension = GraphicStateExtension;
|
|
35362
36667
|
exports.GraphicUtil = GraphicUtil;
|
|
36668
|
+
exports.Grayscale = Grayscale;
|
|
35363
36669
|
exports.Group = Group;
|
|
35364
36670
|
exports.GroupFadeIn = GroupFadeIn;
|
|
35365
36671
|
exports.GroupFadeOut = GroupFadeOut;
|
|
@@ -35438,6 +36744,7 @@
|
|
|
35438
36744
|
exports.POLYGON_NUMBER_TYPE = POLYGON_NUMBER_TYPE;
|
|
35439
36745
|
exports.PURE_STYLE_KEY = PURE_STYLE_KEY;
|
|
35440
36746
|
exports.PYRAMID3D_NUMBER_TYPE = PYRAMID3D_NUMBER_TYPE;
|
|
36747
|
+
exports.Particle = Particle;
|
|
35441
36748
|
exports.Path = Path;
|
|
35442
36749
|
exports.PathRender = PathRender;
|
|
35443
36750
|
exports.PathRenderContribution = PathRenderContribution;
|
|
@@ -35445,6 +36752,7 @@
|
|
|
35445
36752
|
exports.PickItemInterceptor = PickItemInterceptor;
|
|
35446
36753
|
exports.PickServiceInterceptor = PickServiceInterceptor;
|
|
35447
36754
|
exports.PickerService = PickerService;
|
|
36755
|
+
exports.Pixelation = Pixelation;
|
|
35448
36756
|
exports.PluginService = PluginService;
|
|
35449
36757
|
exports.Polygon = Polygon;
|
|
35450
36758
|
exports.PolygonRender = PolygonRender;
|