@visactor/vrender-animate
Version:
This module provides a graph-based animation system for VRender.
238 lines (226 loc) • 24.4 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: !0
}), exports.Dissolve = void 0;
const CustomEffectBase_1 = require("./base/CustomEffectBase"), ImageProcessUtils_1 = require("./base/ImageProcessUtils");
class Dissolve extends CustomEffectBase_1.HybridEffectBase {
constructor(from, to, duration, easing, params) {
var _a, _b, _c, _d;
super(from, to, duration, easing, params), this.noiseData = null;
const rawNoiseScale = null === (_a = null == params ? void 0 : params.options) || void 0 === _a ? void 0 : _a.noiseScale, clampedNoiseScale = void 0 !== rawNoiseScale ? Math.max(0, Math.floor(rawNoiseScale)) : 8;
this.dissolveConfig = {
dissolveType: (null === (_b = null == params ? void 0 : params.options) || void 0 === _b ? void 0 : _b.dissolveType) || "outward",
useWebGL: void 0 === (null === (_c = null == params ? void 0 : params.options) || void 0 === _c ? void 0 : _c.useWebGL) || params.options.useWebGL,
noiseScale: clampedNoiseScale,
fadeEdge: void 0 === (null === (_d = null == params ? void 0 : params.options) || void 0 === _d ? void 0 : _d.fadeEdge) || params.options.fadeEdge
};
}
getShaderSources() {
return {
vertex: ImageProcessUtils_1.ShaderLibrary.STANDARD_VERTEX_SHADER,
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 ${ImageProcessUtils_1.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 `
};
}
applyWebGLEffect(canvas) {
if (!this.gl || !this.program || !this.webglCanvas) return canvas;
this.setupWebGLState(canvas);
const texture = this.createTextureFromCanvas(canvas);
if (!texture) return canvas;
this.noiseData || (this.noiseData = ImageProcessUtils_1.ImageProcessUtils.generateNoiseTexture(256, 256));
const noiseTexture = this.gl.createTexture();
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);
const vertexBuffer = this.createFullScreenQuad();
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;
}
setUniforms() {
if (!this.gl || !this.program || !this.webglCanvas) return;
const textureLocation = this.gl.getUniformLocation(this.program, "u_texture"), noiseTextureLocation = this.gl.getUniformLocation(this.program, "u_noiseTexture"), timeLocation = this.gl.getUniformLocation(this.program, "u_time"), dissolveTypeLocation = this.gl.getUniformLocation(this.program, "u_dissolveType"), resolutionLocation = this.gl.getUniformLocation(this.program, "u_resolution"), noiseScaleLocation = this.gl.getUniformLocation(this.program, "u_noiseScale"), fadeEdgeLocation = this.gl.getUniformLocation(this.program, "u_fadeEdge");
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);
this.gl.uniform1i(dissolveTypeLocation, {
outward: 0,
inward: 1,
radial: 2,
leftToRight: 3,
rightToLeft: 4,
topToBottom: 5,
bottomToTop: 6
}[this.dissolveConfig.dissolveType] || 0);
}
applyCanvas2DEffect(canvas) {
const outputCanvas = this.createOutputCanvas(canvas);
if (!outputCanvas) return canvas;
const {canvas: outputCanvasElement, ctx: ctx} = outputCanvas, imageData = ctx.getImageData(0, 0, canvas.width, canvas.height), progress = this.currentAnimationRatio;
let dissolvedImageData;
switch (this.dissolveConfig.dissolveType) {
case "outward":
dissolvedImageData = this.applyOutwardDissolve(imageData, progress);
break;
case "inward":
dissolvedImageData = this.applyInwardDissolve(imageData, progress);
break;
case "radial":
dissolvedImageData = this.applyRadialDissolve(imageData, progress);
break;
case "leftToRight":
dissolvedImageData = this.applyLeftToRightDissolve(imageData, progress);
break;
case "rightToLeft":
dissolvedImageData = this.applyRightToLeftDissolve(imageData, progress);
break;
case "topToBottom":
dissolvedImageData = this.applyTopToBottomDissolve(imageData, progress);
break;
case "bottomToTop":
dissolvedImageData = this.applyBottomToTopDissolve(imageData, progress);
break;
default:
dissolvedImageData = imageData;
}
return ctx.putImageData(dissolvedImageData, 0, 0), outputCanvasElement;
}
applyOutwardDissolve(imageData, progress) {
const {data: data, width: width, height: height} = imageData, result = new Uint8ClampedArray(data.length);
result.set(data);
const centerX = width / 2, centerY = height / 2, maxDist = Math.sqrt(centerX * centerX + centerY * centerY), pixelSize = this.dissolveConfig.noiseScale;
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
const dx = x - centerX, dy = y - centerY, normalizedDist = Math.sqrt(dx * dx + dy * dy) / maxDist;
let dissolveThreshold = 1.2 - 1.4 * progress, alpha = 1;
if (pixelSize > 0) {
dissolveThreshold += .4 * (ImageProcessUtils_1.ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5),
alpha = normalizedDist > dissolveThreshold ? 0 : 1;
} else if (this.dissolveConfig.fadeEdge) {
const fadeStart = dissolveThreshold - .15;
alpha = normalizedDist < fadeStart ? 1 : normalizedDist > dissolveThreshold ? 0 : 1 - (normalizedDist - fadeStart) / (dissolveThreshold - fadeStart);
} else alpha = normalizedDist > dissolveThreshold ? 0 : 1;
const index = 4 * (y * width + x);
result[index + 3] = Math.floor(result[index + 3] * alpha);
}
return new ImageData(result, width, height);
}
applyInwardDissolve(imageData, progress) {
const {data: data, width: width, height: height} = imageData, result = new Uint8ClampedArray(data.length);
result.set(data);
const centerX = width / 2, centerY = height / 2, maxDist = Math.sqrt(centerX * centerX + centerY * centerY), pixelSize = this.dissolveConfig.noiseScale;
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
const dx = x - centerX, dy = y - centerY, normalizedDist = Math.sqrt(dx * dx + dy * dy) / maxDist;
let dissolveThreshold = 1.4 * progress, alpha = 1;
if (pixelSize > 0) {
dissolveThreshold += .4 * (ImageProcessUtils_1.ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5),
alpha = normalizedDist < dissolveThreshold ? 0 : 1;
} else if (this.dissolveConfig.fadeEdge) {
const fadeEnd = dissolveThreshold + .15;
alpha = normalizedDist < dissolveThreshold ? 0 : normalizedDist > fadeEnd ? 1 : (normalizedDist - dissolveThreshold) / (fadeEnd - dissolveThreshold);
} else alpha = normalizedDist < dissolveThreshold ? 0 : 1;
const index = 4 * (y * width + x);
result[index + 3] = Math.floor(result[index + 3] * alpha);
}
return new ImageData(result, width, height);
}
applyRadialDissolve(imageData, progress) {
const {data: data, width: width, height: height} = imageData, result = new Uint8ClampedArray(data.length);
result.set(data);
const centerX = width / 2, centerY = height / 2, pixelSize = this.dissolveConfig.noiseScale;
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
const dx = x - centerX, dy = y - centerY, normalizedAngle = (Math.atan2(dy, dx) + Math.PI) / (2 * Math.PI);
let dissolveThreshold = 1.2 * progress, alpha = 1;
if (pixelSize > 0) {
dissolveThreshold += .3 * (ImageProcessUtils_1.ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5),
alpha = normalizedAngle < dissolveThreshold ? 0 : 1;
} else if (this.dissolveConfig.fadeEdge) {
const fadeEnd = dissolveThreshold + .08;
alpha = normalizedAngle < dissolveThreshold ? 0 : normalizedAngle > fadeEnd ? 1 : (normalizedAngle - dissolveThreshold) / (fadeEnd - dissolveThreshold);
} else alpha = normalizedAngle < dissolveThreshold ? 0 : 1;
const index = 4 * (y * width + x);
result[index + 3] = Math.floor(result[index + 3] * alpha);
}
return new ImageData(result, width, height);
}
applyLeftToRightDissolve(imageData, progress) {
const {data: data, width: width, height: height} = imageData, result = new Uint8ClampedArray(data.length);
result.set(data);
const pixelSize = this.dissolveConfig.noiseScale;
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
const normalizedX = x / width;
let dissolveThreshold = 1.2 * progress, alpha = 1;
if (pixelSize > 0) {
dissolveThreshold += .3 * (ImageProcessUtils_1.ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5),
alpha = normalizedX < dissolveThreshold ? 0 : 1;
} else if (this.dissolveConfig.fadeEdge) {
const fadeEnd = dissolveThreshold + .08;
alpha = normalizedX < dissolveThreshold ? 0 : normalizedX > fadeEnd ? 1 : (normalizedX - dissolveThreshold) / (fadeEnd - dissolveThreshold);
} else alpha = normalizedX < dissolveThreshold ? 0 : 1;
const index = 4 * (y * width + x);
result[index + 3] = Math.floor(result[index + 3] * alpha);
}
return new ImageData(result, width, height);
}
applyRightToLeftDissolve(imageData, progress) {
const {data: data, width: width, height: height} = imageData, result = new Uint8ClampedArray(data.length);
result.set(data);
const pixelSize = this.dissolveConfig.noiseScale;
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
const normalizedX = x / width;
let dissolveThreshold = 1 - 1.2 * progress, alpha = 1;
if (pixelSize > 0) {
dissolveThreshold += .3 * (ImageProcessUtils_1.ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5),
alpha = normalizedX > dissolveThreshold ? 0 : 1;
} else if (this.dissolveConfig.fadeEdge) {
const fadeStart = dissolveThreshold - .08;
alpha = normalizedX < fadeStart ? 1 : normalizedX > dissolveThreshold ? 0 : 1 - (normalizedX - fadeStart) / (dissolveThreshold - fadeStart);
} else alpha = normalizedX > dissolveThreshold ? 0 : 1;
const index = 4 * (y * width + x);
result[index + 3] = Math.floor(result[index + 3] * alpha);
}
return new ImageData(result, width, height);
}
applyTopToBottomDissolve(imageData, progress) {
const {data: data, width: width, height: height} = imageData, result = new Uint8ClampedArray(data.length);
result.set(data);
const pixelSize = this.dissolveConfig.noiseScale;
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
const normalizedY = y / height;
let dissolveThreshold = 1.2 * progress, alpha = 1;
if (pixelSize > 0) {
dissolveThreshold += .3 * (ImageProcessUtils_1.ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5),
alpha = normalizedY < dissolveThreshold ? 0 : 1;
} else if (this.dissolveConfig.fadeEdge) {
const fadeEnd = dissolveThreshold + .08;
alpha = normalizedY < dissolveThreshold ? 0 : normalizedY > fadeEnd ? 1 : (normalizedY - dissolveThreshold) / (fadeEnd - dissolveThreshold);
} else alpha = normalizedY < dissolveThreshold ? 0 : 1;
const index = 4 * (y * width + x);
result[index + 3] = Math.floor(result[index + 3] * alpha);
}
return new ImageData(result, width, height);
}
applyBottomToTopDissolve(imageData, progress) {
const {data: data, width: width, height: height} = imageData, result = new Uint8ClampedArray(data.length);
result.set(data);
const pixelSize = this.dissolveConfig.noiseScale;
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
const normalizedY = y / height;
let dissolveThreshold = 1 - 1.2 * progress, alpha = 1;
if (pixelSize > 0) {
dissolveThreshold += .3 * (ImageProcessUtils_1.ImageProcessUtils.pixelNoise(x, y, pixelSize) - .5),
alpha = normalizedY > dissolveThreshold ? 0 : 1;
} else if (this.dissolveConfig.fadeEdge) {
const fadeStart = dissolveThreshold - .08;
alpha = normalizedY < fadeStart ? 1 : normalizedY > dissolveThreshold ? 0 : 1 - (normalizedY - fadeStart) / (dissolveThreshold - fadeStart);
} else alpha = normalizedY > dissolveThreshold ? 0 : 1;
const index = 4 * (y * width + x);
result[index + 3] = Math.floor(result[index + 3] * alpha);
}
return new ImageData(result, width, height);
}
}
exports.Dissolve = Dissolve;
//# sourceMappingURL=dissolve.js.map