mirror of
https://github.com/DavidHDev/vue-bits.git
synced 2026-03-07 06:29:30 -07:00
1 line
2.5 KiB
JSON
1 line
2.5 KiB
JSON
{"name":"Noise","title":"Noise","description":"Animated film grain / noise overlay adding subtle texture and motion.","type":"registry:component","add":"when-added","files":[{"type":"registry:component","role":"file","content":"<template>\n <canvas\n ref=\"grainRef\"\n class=\"pointer-events-none absolute top-0 left-0 h-screen w-screen\"\n :style=\"`image-rendering: pixelated; mix-blend-mode: ${props.mixBlendMode}`\"\n ></canvas>\n</template>\n\n<script setup lang=\"ts\">\nimport { onMounted, onBeforeUnmount, useTemplateRef } from 'vue';\n\ninterface NoiseProps {\n patternRefreshInterval?: number;\n patternAlpha?: number;\n mixBlendMode?: string;\n}\n\nconst props = withDefaults(defineProps<NoiseProps>(), {\n patternRefreshInterval: 2,\n patternAlpha: 10,\n mixBlendMode: 'normal'\n});\n\nconst grainRef = useTemplateRef<HTMLCanvasElement>('grainRef');\n\nlet animationId = 0;\nlet frame = 0;\nconst canvasSize = 1024;\n\nconst resize = () => {\n const canvas = grainRef.value;\n if (!canvas) return;\n canvas.width = canvasSize;\n canvas.height = canvasSize;\n canvas.style.width = '100vw';\n canvas.style.height = '100vh';\n};\n\nlet noiseData: ImageData;\nlet noise32: Uint32Array;\n\nconst initImageData = (ctx: CanvasRenderingContext2D) => {\n noiseData = ctx.createImageData(canvasSize, canvasSize);\n noise32 = new Uint32Array(noiseData.data.buffer);\n};\n\nconst drawGrain = () => {\n const a = props.patternAlpha << 24;\n for (let i = 0; i < noise32.length; i++) {\n const v = (Math.random() * 255) | 0;\n noise32[i] = a | (v << 16) | (v << 8) | v;\n }\n};\n\nconst loop = (ctx: CanvasRenderingContext2D) => {\n if (frame % Math.max(1, Math.round(props.patternRefreshInterval)) === 0) {\n drawGrain();\n ctx.putImageData(noiseData, 0, 0);\n }\n frame++;\n animationId = requestAnimationFrame(() => loop(ctx));\n};\n\nonMounted(() => {\n const canvas = grainRef.value;\n if (!canvas) return;\n const ctx = canvas.getContext('2d', { alpha: true });\n if (!ctx) return;\n\n resize();\n initImageData(ctx);\n drawGrain();\n ctx.putImageData(noiseData, 0, 0);\n loop(ctx);\n\n window.addEventListener('resize', resize);\n});\n\nonBeforeUnmount(() => {\n window.removeEventListener('resize', resize);\n cancelAnimationFrame(animationId);\n});\n</script>\n","path":"Noise/Noise.vue","_imports_":[],"registryDependencies":[],"dependencies":[],"devDependencies":[]}],"registryDependencies":[],"dependencies":[],"devDependencies":[],"categories":["Animations"]} |