UNPKG

@visactor/vrender-animate

Version:

This module provides a graph-based animation system for VRender.

162 lines (154 loc) 9.82 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: !0 }), exports.Glitch = void 0; const CustomEffectBase_1 = require("./base/CustomEffectBase"), ImageProcessUtils_1 = require("./base/ImageProcessUtils"); class Glitch extends CustomEffectBase_1.Canvas2DEffectBase { constructor(from, to, duration, easing, params) { var _a, _b; super(from, to, duration, easing, params), this.glitchConfig = { effectType: (null === (_a = null == params ? void 0 : params.options) || void 0 === _a ? void 0 : _a.effectType) || "rgb-shift", intensity: void 0 !== (null === (_b = null == params ? void 0 : params.options) || void 0 === _b ? void 0 : _b.intensity) ? params.options.intensity : .5 }; } applyCanvas2DEffect(canvas) { if (this.glitchConfig.intensity <= 0) { const outputCanvas = this.createOutputCanvas(canvas); return outputCanvas ? outputCanvas.canvas : null; } try { switch (this.glitchConfig.effectType) { case "rgb-shift": default: return this.applyRGBShiftGlitch(canvas); case "digital-distortion": return this.applyDigitalDistortionGlitch(canvas); case "scan-lines": return this.applyScanLineGlitch(canvas); case "data-corruption": return this.applyDataCorruptionGlitch(canvas); } } catch (error) { return console.warn("Glitch effect failed:", error), null; } } applyRGBShiftGlitch(canvas) { const outputCanvas = this.createOutputCanvas(canvas); if (!outputCanvas) return null; const {ctx: ctx} = outputCanvas; try { ctx.clearRect(0, 0, canvas.width, canvas.height); const dynamicIntensity = ImageProcessUtils_1.ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime()), maxOffset = Math.floor(20 * dynamicIntensity), redOffset = this.generateRandomOffset(maxOffset), greenOffset = this.generateRandomOffset(maxOffset, .3), blueOffset = this.generateRandomOffset(-maxOffset), tempCanvas = ImageProcessUtils_1.ImageProcessUtils.createTempCanvas(canvas.width, canvas.height), tempCtx = tempCanvas.getContext("2d"); tempCtx.drawImage(canvas, 0, 0); const originalImageData = tempCtx.getImageData(0, 0, canvas.width, canvas.height), redChannelData = ImageProcessUtils_1.ImageProcessUtils.extractChannel(originalImageData, 0), greenChannelData = ImageProcessUtils_1.ImageProcessUtils.extractChannel(originalImageData, 1), blueChannelData = ImageProcessUtils_1.ImageProcessUtils.extractChannel(originalImageData, 2); 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; } catch (error) { return console.warn("RGB shift glitch failed:", error), null; } } applyDigitalDistortionGlitch(canvas) { const outputCanvas = this.createOutputCanvas(canvas); if (!outputCanvas) return null; const {ctx: ctx} = outputCanvas; try { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height), dynamicIntensity = ImageProcessUtils_1.ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime()), distortedImageData = this.processDigitalDistortion(imageData, dynamicIntensity); return ctx.clearRect(0, 0, canvas.width, canvas.height), ctx.putImageData(distortedImageData, 0, 0), outputCanvas.canvas; } catch (error) { return console.warn("Digital distortion glitch failed:", error), null; } } applyScanLineGlitch(canvas) { const outputCanvas = this.createOutputCanvas(canvas); if (!outputCanvas) return null; const {ctx: ctx} = outputCanvas; try { const dynamicIntensity = ImageProcessUtils_1.ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime()), lineSpacing = Math.max(2, Math.floor(10 - 8 * dynamicIntensity)); ctx.globalCompositeOperation = "multiply"; for (let y = 0; y < canvas.height; y += lineSpacing) if (Math.random() < dynamicIntensity) { const opacity = .1 + .4 * dynamicIntensity; ctx.fillStyle = `rgba(0, 0, 0, ${opacity})`, ctx.fillRect(0, y, canvas.width, 1); } ctx.globalCompositeOperation = "screen"; const brightLineCount = Math.floor(20 * dynamicIntensity); for (let i = 0; i < brightLineCount; i++) { const y = Math.random() * canvas.height, opacity = .3 * dynamicIntensity; ctx.fillStyle = `rgba(255, 255, 255, ${opacity})`, ctx.fillRect(0, Math.floor(y), canvas.width, 1); } return ctx.globalCompositeOperation = "source-over", outputCanvas.canvas; } catch (error) { return console.warn("Scan line glitch failed:", error), null; } } applyDataCorruptionGlitch(canvas) { const outputCanvas = this.createOutputCanvas(canvas); if (!outputCanvas) return null; const {ctx: ctx} = outputCanvas; try { const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height), dynamicIntensity = ImageProcessUtils_1.ImageProcessUtils.calculateDynamicStrength(this.glitchConfig.intensity, this.getAnimationTime()), corruptedImageData = this.processDataCorruption(imageData, dynamicIntensity); return ctx.clearRect(0, 0, canvas.width, canvas.height), ctx.putImageData(corruptedImageData, 0, 0), outputCanvas.canvas; } catch (error) { return console.warn("Data corruption glitch failed:", error), null; } } generateRandomOffset(maxOffset, scale = 1) { return { x: (Math.random() - .5) * maxOffset, y: (Math.random() - .5) * maxOffset * scale }; } processDigitalDistortion(imageData, intensity) { const {data: data, width: width, height: height} = imageData, result = new Uint8ClampedArray(data), sliceCount = Math.floor(20 * intensity) + 5, sliceHeight = Math.floor(height / sliceCount); for (let i = 0; i < sliceCount; i++) if (Math.random() < intensity) { const y = i * sliceHeight, sliceEnd = Math.min(y + sliceHeight, height), offset = Math.floor((Math.random() - .5) * width * intensity * .1); this.shiftSliceHorizontal(result, width, height, y, sliceEnd, offset); } const noiseIntensity = .3 * intensity; 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()); return new ImageData(result, width, height); } shiftSliceHorizontal(data, width, height, startY, endY, offset) { const tempRow = new Uint8ClampedArray(4 * width); for (let y = startY; y < endY; y++) { const rowStart = y * width * 4; for (let x = 0; x < 4 * width; x++) tempRow[x] = data[rowStart + x]; for (let x = 0; x < width; x++) { const targetIndex = rowStart + 4 * x, sourceIndex = 4 * ((x - offset + width) % width); data[targetIndex] = tempRow[sourceIndex], data[targetIndex + 1] = tempRow[sourceIndex + 1], data[targetIndex + 2] = tempRow[sourceIndex + 2], data[targetIndex + 3] = tempRow[sourceIndex + 3]; } } } processDataCorruption(imageData, intensity) { const {data: data, width: width, height: height} = imageData, result = new Uint8ClampedArray(data), stripeCount = Math.floor(15 * intensity) + 5; for (let i = 0; i < stripeCount; i++) if (Math.random() < intensity) { const x = Math.floor(Math.random() * width), stripeWidth = Math.floor(5 * Math.random()) + 1, color = Math.random() < .5 ? 0 : 255; for (let y = 0; y < height; y++) for (let dx = 0; dx < stripeWidth && x + dx < width; dx++) { const index = 4 * (y * width + x + dx); result[index] = color, result[index + 1] = color, result[index + 2] = color; } } const corruptionCount = Math.floor(20 * intensity); for (let i = 0; i < corruptionCount; i++) { const blockX = Math.floor(Math.random() * width), blockY = Math.floor(Math.random() * height), blockW = Math.floor(20 * Math.random()) + 5, blockH = Math.floor(10 * Math.random()) + 2; this.corruptBlock(result, width, height, blockX, blockY, blockW, blockH); } return new ImageData(result, width, height); } corruptBlock(data, width, height, x, y, w, h) { for (let dy = 0; dy < h && y + dy < height; dy++) for (let dx = 0; dx < w && x + dx < width; dx++) { const index = 4 * ((y + dy) * width + (x + dx)); Math.random() < .7 && (data[index] = 255 * Math.random(), data[index + 1] = 255 * Math.random(), data[index + 2] = 255 * Math.random()); } } } exports.Glitch = Glitch; //# sourceMappingURL=glitch.js.map