Files
2025-10-16 21:45:52 -07:00

11 lines
1.9 KiB
JSON

{
"name": "pixel-image",
"description": "Pixelated image effect",
"files": [
{
"name": "pixel-image.tsx",
"content": "\"use client\"\n\nimport * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface PixelImageProps\n extends React.CanvasHTMLAttributes<HTMLCanvasElement> {\n src: string\n pixelSize?: number\n}\n\nconst PixelImage = React.forwardRef<HTMLCanvasElement, PixelImageProps>(\n ({ className, src, pixelSize = 10, ...props }, ref) => {\n const canvasRef = React.useRef<HTMLCanvasElement>(null)\n\n React.useEffect(() => {\n const canvas = canvasRef.current\n if (!canvas) return\n\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return\n\n const img = new Image()\n img.crossOrigin = \"anonymous\"\n img.src = src\n\n img.onload = () => {\n canvas.width = img.width\n canvas.height = img.height\n\n ctx.imageSmoothingEnabled = false\n ctx.drawImage(img, 0, 0)\n\n const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height)\n ctx.clearRect(0, 0, canvas.width, canvas.height)\n\n for (let y = 0; y < canvas.height; y += pixelSize) {\n for (let x = 0; x < canvas.width; x += pixelSize) {\n const pixelIndex = (y * canvas.width + x) * 4\n const r = imageData.data[pixelIndex]\n const g = imageData.data[pixelIndex + 1]\n const b = imageData.data[pixelIndex + 2]\n const a = imageData.data[pixelIndex + 3] / 255\n\n ctx.fillStyle = `rgba(${r}, ${g}, ${b}, ${a})`\n ctx.fillRect(x, y, pixelSize, pixelSize)\n }\n }\n }\n }, [src, pixelSize])\n\n return (\n <canvas\n ref={canvasRef}\n className={cn(\"max-w-full\", className)}\n {...props}\n />\n )\n }\n)\nPixelImage.displayName = \"PixelImage\"\n\nexport { PixelImage }\n"
}
],
"type": "components:ui"
}