From 98a7353f616bd20e888b200898d4515e4d9b2a32 Mon Sep 17 00:00:00 2001 From: KhaledSaeed18 Date: Thu, 14 May 2026 13:10:32 +0300 Subject: [PATCH] fix: resync canvas size on browser zoom change in ElectricBorder --- public/r/ElectricBorder-JS-CSS.json | 2 +- public/r/ElectricBorder-JS-TW.json | 2 +- public/r/ElectricBorder-TS-CSS.json | 2 +- public/r/ElectricBorder-TS-TW.json | 2 +- .../Animations/ElectricBorder/ElectricBorder.jsx | 11 +++++++++-- .../Animations/ElectricBorder/ElectricBorder.jsx | 10 +++++++++- .../Animations/ElectricBorder/ElectricBorder.tsx | 10 +++++++++- .../Animations/ElectricBorder/ElectricBorder.tsx | 10 +++++++++- 8 files changed, 40 insertions(+), 9 deletions(-) diff --git a/public/r/ElectricBorder-JS-CSS.json b/public/r/ElectricBorder-JS-CSS.json index 8af5ad681..a9e0467a1 100644 --- a/public/r/ElectricBorder-JS-CSS.json +++ b/public/r/ElectricBorder-JS-CSS.json @@ -13,7 +13,7 @@ { "type": "registry:component", "path": "ElectricBorder/ElectricBorder.jsx", - "content": "import { useEffect, useRef, useCallback } from 'react';\nimport './ElectricBorder.css';\n\nconst ElectricBorder = ({\n children,\n color = '#5227FF',\n speed = 1,\n chaos = 0.12,\n borderRadius = 24,\n className,\n style\n}) => {\n const canvasRef = useRef(null);\n const containerRef = useRef(null);\n const animationRef = useRef(null);\n const timeRef = useRef(0);\n const lastFrameTimeRef = useRef(0);\n\n // Noise functions\n const random = useCallback(x => {\n return (Math.sin(x * 12.9898) * 43758.5453) % 1;\n }, []);\n\n const noise2D = useCallback(\n (x, y) => {\n const i = Math.floor(x);\n const j = Math.floor(y);\n const fx = x - i;\n const fy = y - j;\n\n const a = random(i + j * 57);\n const b = random(i + 1 + j * 57);\n const c = random(i + (j + 1) * 57);\n const d = random(i + 1 + (j + 1) * 57);\n\n const ux = fx * fx * (3.0 - 2.0 * fx);\n const uy = fy * fy * (3.0 - 2.0 * fy);\n\n return a * (1 - ux) * (1 - uy) + b * ux * (1 - uy) + c * (1 - ux) * uy + d * ux * uy;\n },\n [random]\n );\n\n const octavedNoise = useCallback(\n (x, octaves, lacunarity, gain, baseAmplitude, baseFrequency, time, seed, baseFlatness) => {\n let y = 0;\n let amplitude = baseAmplitude;\n let frequency = baseFrequency;\n\n for (let i = 0; i < octaves; i++) {\n let octaveAmplitude = amplitude;\n if (i === 0) {\n octaveAmplitude *= baseFlatness;\n }\n y += octaveAmplitude * noise2D(frequency * x + seed * 100, time * frequency * 0.3);\n frequency *= lacunarity;\n amplitude *= gain;\n }\n\n return y;\n },\n [noise2D]\n );\n\n const getCornerPoint = useCallback((centerX, centerY, radius, startAngle, arcLength, progress) => {\n const angle = startAngle + progress * arcLength;\n return {\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n };\n }, []);\n\n const getRoundedRectPoint = useCallback(\n (t, left, top, width, height, radius) => {\n const straightWidth = width - 2 * radius;\n const straightHeight = height - 2 * radius;\n const cornerArc = (Math.PI * radius) / 2;\n const totalPerimeter = 2 * straightWidth + 2 * straightHeight + 4 * cornerArc;\n const distance = t * totalPerimeter;\n\n let accumulated = 0;\n\n // Top edge\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + radius + progress * straightWidth, y: top };\n }\n accumulated += straightWidth;\n\n // Top-right corner\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + radius, radius, -Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n // Right edge\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left + width, y: top + radius + progress * straightHeight };\n }\n accumulated += straightHeight;\n\n // Bottom-right corner\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + height - radius, radius, 0, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n // Bottom edge\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + width - radius - progress * straightWidth, y: top + height };\n }\n accumulated += straightWidth;\n\n // Bottom-left corner\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + height - radius, radius, Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n // Left edge\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left, y: top + height - radius - progress * straightHeight };\n }\n accumulated += straightHeight;\n\n // Top-left corner\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + radius, radius, Math.PI, Math.PI / 2, progress);\n },\n [getCornerPoint]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n // Configuration\n const octaves = 10;\n const lacunarity = 1.6;\n const gain = 0.7;\n const amplitude = chaos;\n const frequency = 10;\n const baseFlatness = 0;\n const displacement = 60;\n const borderOffset = 60;\n\n const updateSize = () => {\n const rect = container.getBoundingClientRect();\n const width = rect.width + borderOffset * 2;\n const height = rect.height + borderOffset * 2;\n\n // Use device pixel ratio for sharp rendering\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n ctx.scale(dpr, dpr);\n\n return { width, height };\n };\n\n let { width, height } = updateSize();\n\n const drawElectricBorder = currentTime => {\n if (!canvas || !ctx) return;\n\n const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000;\n timeRef.current += deltaTime * speed;\n lastFrameTimeRef.current = currentTime;\n\n // Clear canvas\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.scale(dpr, dpr);\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 1;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n const scale = displacement;\n const left = borderOffset;\n const top = borderOffset;\n const borderWidth = width - 2 * borderOffset;\n const borderHeight = height - 2 * borderOffset;\n const maxRadius = Math.min(borderWidth, borderHeight) / 2;\n const radius = Math.min(borderRadius, maxRadius);\n\n const approximatePerimeter = 2 * (borderWidth + borderHeight) + 2 * Math.PI * radius;\n const sampleCount = Math.floor(approximatePerimeter / 2);\n\n ctx.beginPath();\n\n for (let i = 0; i <= sampleCount; i++) {\n const progress = i / sampleCount;\n\n const point = getRoundedRectPoint(progress, left, top, borderWidth, borderHeight, radius);\n\n const xNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 0,\n baseFlatness\n );\n\n const yNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 1,\n baseFlatness\n );\n\n const displacedX = point.x + xNoise * scale;\n const displacedY = point.y + yNoise * scale;\n\n if (i === 0) {\n ctx.moveTo(displacedX, displacedY);\n } else {\n ctx.lineTo(displacedX, displacedY);\n }\n }\n\n ctx.closePath();\n ctx.stroke();\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n };\n\n // Handle resize\n const resizeObserver = new ResizeObserver(() => {\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n });\n resizeObserver.observe(container);\n\n // Start animation\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n\n return () => {\n if (animationRef.current) {\n cancelAnimationFrame(animationRef.current);\n }\n resizeObserver.disconnect();\n };\n }, [color, speed, chaos, borderRadius, octavedNoise, getRoundedRectPoint]);\n\n const vars = {\n '--electric-border-color': color,\n borderRadius: borderRadius\n };\n\n return (\n
\n
\n \n
\n
\n
\n
\n
\n
\n
{children}
\n
\n );\n};\n\nexport default ElectricBorder;\n" + "content": "import { useEffect, useRef, useCallback } from 'react';\nimport './ElectricBorder.css';\n\nconst ElectricBorder = ({\n children,\n color = '#5227FF',\n speed = 1,\n chaos = 0.12,\n borderRadius = 24,\n className,\n style\n}) => {\n const canvasRef = useRef(null);\n const containerRef = useRef(null);\n const animationRef = useRef(null);\n const timeRef = useRef(0);\n const lastFrameTimeRef = useRef(0);\n\n // Noise functions\n const random = useCallback(x => {\n return (Math.sin(x * 12.9898) * 43758.5453) % 1;\n }, []);\n\n const noise2D = useCallback(\n (x, y) => {\n const i = Math.floor(x);\n const j = Math.floor(y);\n const fx = x - i;\n const fy = y - j;\n\n const a = random(i + j * 57);\n const b = random(i + 1 + j * 57);\n const c = random(i + (j + 1) * 57);\n const d = random(i + 1 + (j + 1) * 57);\n\n const ux = fx * fx * (3.0 - 2.0 * fx);\n const uy = fy * fy * (3.0 - 2.0 * fy);\n\n return a * (1 - ux) * (1 - uy) + b * ux * (1 - uy) + c * (1 - ux) * uy + d * ux * uy;\n },\n [random]\n );\n\n const octavedNoise = useCallback(\n (x, octaves, lacunarity, gain, baseAmplitude, baseFrequency, time, seed, baseFlatness) => {\n let y = 0;\n let amplitude = baseAmplitude;\n let frequency = baseFrequency;\n\n for (let i = 0; i < octaves; i++) {\n let octaveAmplitude = amplitude;\n if (i === 0) {\n octaveAmplitude *= baseFlatness;\n }\n y += octaveAmplitude * noise2D(frequency * x + seed * 100, time * frequency * 0.3);\n frequency *= lacunarity;\n amplitude *= gain;\n }\n\n return y;\n },\n [noise2D]\n );\n\n const getCornerPoint = useCallback((centerX, centerY, radius, startAngle, arcLength, progress) => {\n const angle = startAngle + progress * arcLength;\n return {\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n };\n }, []);\n\n const getRoundedRectPoint = useCallback(\n (t, left, top, width, height, radius) => {\n const straightWidth = width - 2 * radius;\n const straightHeight = height - 2 * radius;\n const cornerArc = (Math.PI * radius) / 2;\n const totalPerimeter = 2 * straightWidth + 2 * straightHeight + 4 * cornerArc;\n const distance = t * totalPerimeter;\n\n let accumulated = 0;\n\n // Top edge\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + radius + progress * straightWidth, y: top };\n }\n accumulated += straightWidth;\n\n // Top-right corner\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + radius, radius, -Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n // Right edge\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left + width, y: top + radius + progress * straightHeight };\n }\n accumulated += straightHeight;\n\n // Bottom-right corner\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + height - radius, radius, 0, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n // Bottom edge\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + width - radius - progress * straightWidth, y: top + height };\n }\n accumulated += straightWidth;\n\n // Bottom-left corner\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + height - radius, radius, Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n // Left edge\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left, y: top + height - radius - progress * straightHeight };\n }\n accumulated += straightHeight;\n\n // Top-left corner\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + radius, radius, Math.PI, Math.PI / 2, progress);\n },\n [getCornerPoint]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n // Configuration\n const octaves = 10;\n const lacunarity = 1.6;\n const gain = 0.7;\n const amplitude = chaos;\n const frequency = 10;\n const baseFlatness = 0;\n const displacement = 60;\n const borderOffset = 60;\n\n const updateSize = () => {\n const rect = container.getBoundingClientRect();\n const width = rect.width + borderOffset * 2;\n const height = rect.height + borderOffset * 2;\n\n // Use device pixel ratio for sharp rendering\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n ctx.scale(dpr, dpr);\n\n return { width, height };\n };\n\n let { width, height } = updateSize();\n let lastDpr = Math.min(window.devicePixelRatio || 1, 2);\n\n const drawElectricBorder = currentTime => {\n if (!canvas || !ctx) return;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n if (dpr !== lastDpr) {\n lastDpr = dpr;\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n }\n\n const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000;\n timeRef.current += deltaTime * speed;\n lastFrameTimeRef.current = currentTime;\n\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.scale(dpr, dpr);\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 1;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n const scale = displacement;\n const left = borderOffset;\n const top = borderOffset;\n const borderWidth = width - 2 * borderOffset;\n const borderHeight = height - 2 * borderOffset;\n const maxRadius = Math.min(borderWidth, borderHeight) / 2;\n const radius = Math.min(borderRadius, maxRadius);\n\n const approximatePerimeter = 2 * (borderWidth + borderHeight) + 2 * Math.PI * radius;\n const sampleCount = Math.floor(approximatePerimeter / 2);\n\n ctx.beginPath();\n\n for (let i = 0; i <= sampleCount; i++) {\n const progress = i / sampleCount;\n\n const point = getRoundedRectPoint(progress, left, top, borderWidth, borderHeight, radius);\n\n const xNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 0,\n baseFlatness\n );\n\n const yNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 1,\n baseFlatness\n );\n\n const displacedX = point.x + xNoise * scale;\n const displacedY = point.y + yNoise * scale;\n\n if (i === 0) {\n ctx.moveTo(displacedX, displacedY);\n } else {\n ctx.lineTo(displacedX, displacedY);\n }\n }\n\n ctx.closePath();\n ctx.stroke();\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n };\n\n // Handle resize\n const resizeObserver = new ResizeObserver(() => {\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n });\n resizeObserver.observe(container);\n\n // Start animation\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n\n return () => {\n if (animationRef.current) {\n cancelAnimationFrame(animationRef.current);\n }\n resizeObserver.disconnect();\n };\n }, [color, speed, chaos, borderRadius, octavedNoise, getRoundedRectPoint]);\n\n const vars = {\n '--electric-border-color': color,\n borderRadius: borderRadius\n };\n\n return (\n
\n
\n \n
\n
\n
\n
\n
\n
\n
{children}
\n
\n );\n};\n\nexport default ElectricBorder;\n" } ], "registryDependencies": [], diff --git a/public/r/ElectricBorder-JS-TW.json b/public/r/ElectricBorder-JS-TW.json index 282fe05ac..86dddb5be 100644 --- a/public/r/ElectricBorder-JS-TW.json +++ b/public/r/ElectricBorder-JS-TW.json @@ -8,7 +8,7 @@ { "type": "registry:component", "path": "ElectricBorder/ElectricBorder.jsx", - "content": "import { useEffect, useRef, useCallback } from 'react';\n\nfunction hexToRgba(hex, alpha = 1) {\n if (!hex) return `rgba(0,0,0,${alpha})`;\n let h = hex.replace('#', '');\n if (h.length === 3) {\n h = h\n .split('')\n .map(c => c + c)\n .join('');\n }\n const int = parseInt(h, 16);\n const r = (int >> 16) & 255;\n const g = (int >> 8) & 255;\n const b = int & 255;\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\nconst ElectricBorder = ({\n children,\n color = '#5227FF',\n speed = 1,\n chaos = 0.12,\n borderRadius = 24,\n className,\n style\n}) => {\n const canvasRef = useRef(null);\n const containerRef = useRef(null);\n const animationRef = useRef(null);\n const timeRef = useRef(0);\n const lastFrameTimeRef = useRef(0);\n\n const random = useCallback(x => {\n return (Math.sin(x * 12.9898) * 43758.5453) % 1;\n }, []);\n\n const noise2D = useCallback(\n (x, y) => {\n const i = Math.floor(x);\n const j = Math.floor(y);\n const fx = x - i;\n const fy = y - j;\n\n const a = random(i + j * 57);\n const b = random(i + 1 + j * 57);\n const c = random(i + (j + 1) * 57);\n const d = random(i + 1 + (j + 1) * 57);\n\n const ux = fx * fx * (3.0 - 2.0 * fx);\n const uy = fy * fy * (3.0 - 2.0 * fy);\n\n return a * (1 - ux) * (1 - uy) + b * ux * (1 - uy) + c * (1 - ux) * uy + d * ux * uy;\n },\n [random]\n );\n\n const octavedNoise = useCallback(\n (x, octaves, lacunarity, gain, baseAmplitude, baseFrequency, time, seed, baseFlatness) => {\n let y = 0;\n let amplitude = baseAmplitude;\n let frequency = baseFrequency;\n\n for (let i = 0; i < octaves; i++) {\n let octaveAmplitude = amplitude;\n if (i === 0) {\n octaveAmplitude *= baseFlatness;\n }\n y += octaveAmplitude * noise2D(frequency * x + seed * 100, time * frequency * 0.3);\n frequency *= lacunarity;\n amplitude *= gain;\n }\n\n return y;\n },\n [noise2D]\n );\n\n const getCornerPoint = useCallback((centerX, centerY, radius, startAngle, arcLength, progress) => {\n const angle = startAngle + progress * arcLength;\n return {\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n };\n }, []);\n\n const getRoundedRectPoint = useCallback(\n (t, left, top, width, height, radius) => {\n const straightWidth = width - 2 * radius;\n const straightHeight = height - 2 * radius;\n const cornerArc = (Math.PI * radius) / 2;\n const totalPerimeter = 2 * straightWidth + 2 * straightHeight + 4 * cornerArc;\n const distance = t * totalPerimeter;\n\n let accumulated = 0;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + radius + progress * straightWidth, y: top };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + radius, radius, -Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left + width, y: top + radius + progress * straightHeight };\n }\n accumulated += straightHeight;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + height - radius, radius, 0, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + width - radius - progress * straightWidth, y: top + height };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + height - radius, radius, Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left, y: top + height - radius - progress * straightHeight };\n }\n accumulated += straightHeight;\n\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + radius, radius, Math.PI, Math.PI / 2, progress);\n },\n [getCornerPoint]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const octaves = 10;\n const lacunarity = 1.6;\n const gain = 0.7;\n const amplitude = chaos;\n const frequency = 10;\n const baseFlatness = 0;\n const displacement = 60;\n const borderOffset = 60;\n\n const updateSize = () => {\n const rect = container.getBoundingClientRect();\n const width = rect.width + borderOffset * 2;\n const height = rect.height + borderOffset * 2;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n ctx.scale(dpr, dpr);\n\n return { width, height };\n };\n\n let { width, height } = updateSize();\n\n const drawElectricBorder = currentTime => {\n if (!canvas || !ctx) return;\n\n const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000;\n timeRef.current += deltaTime * speed;\n lastFrameTimeRef.current = currentTime;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.scale(dpr, dpr);\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 1;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n const scale = displacement;\n const left = borderOffset;\n const top = borderOffset;\n const borderWidth = width - 2 * borderOffset;\n const borderHeight = height - 2 * borderOffset;\n const maxRadius = Math.min(borderWidth, borderHeight) / 2;\n const radius = Math.min(borderRadius, maxRadius);\n\n const approximatePerimeter = 2 * (borderWidth + borderHeight) + 2 * Math.PI * radius;\n const sampleCount = Math.floor(approximatePerimeter / 2);\n\n ctx.beginPath();\n\n for (let i = 0; i <= sampleCount; i++) {\n const progress = i / sampleCount;\n\n const point = getRoundedRectPoint(progress, left, top, borderWidth, borderHeight, radius);\n\n const xNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 0,\n baseFlatness\n );\n const yNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 1,\n baseFlatness\n );\n\n const displacedX = point.x + xNoise * scale;\n const displacedY = point.y + yNoise * scale;\n\n if (i === 0) {\n ctx.moveTo(displacedX, displacedY);\n } else {\n ctx.lineTo(displacedX, displacedY);\n }\n }\n\n ctx.closePath();\n ctx.stroke();\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n };\n\n const resizeObserver = new ResizeObserver(() => {\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n });\n resizeObserver.observe(container);\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n\n return () => {\n if (animationRef.current) {\n cancelAnimationFrame(animationRef.current);\n }\n resizeObserver.disconnect();\n };\n }, [color, speed, chaos, borderRadius, octavedNoise, getRoundedRectPoint]);\n\n return (\n \n
\n \n
\n
\n \n \n \n
\n
{children}
\n
\n );\n};\n\nexport default ElectricBorder;\n" + "content": "import { useEffect, useRef, useCallback } from 'react';\n\nfunction hexToRgba(hex, alpha = 1) {\n if (!hex) return `rgba(0,0,0,${alpha})`;\n let h = hex.replace('#', '');\n if (h.length === 3) {\n h = h\n .split('')\n .map(c => c + c)\n .join('');\n }\n const int = parseInt(h, 16);\n const r = (int >> 16) & 255;\n const g = (int >> 8) & 255;\n const b = int & 255;\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\nconst ElectricBorder = ({\n children,\n color = '#5227FF',\n speed = 1,\n chaos = 0.12,\n borderRadius = 24,\n className,\n style\n}) => {\n const canvasRef = useRef(null);\n const containerRef = useRef(null);\n const animationRef = useRef(null);\n const timeRef = useRef(0);\n const lastFrameTimeRef = useRef(0);\n\n const random = useCallback(x => {\n return (Math.sin(x * 12.9898) * 43758.5453) % 1;\n }, []);\n\n const noise2D = useCallback(\n (x, y) => {\n const i = Math.floor(x);\n const j = Math.floor(y);\n const fx = x - i;\n const fy = y - j;\n\n const a = random(i + j * 57);\n const b = random(i + 1 + j * 57);\n const c = random(i + (j + 1) * 57);\n const d = random(i + 1 + (j + 1) * 57);\n\n const ux = fx * fx * (3.0 - 2.0 * fx);\n const uy = fy * fy * (3.0 - 2.0 * fy);\n\n return a * (1 - ux) * (1 - uy) + b * ux * (1 - uy) + c * (1 - ux) * uy + d * ux * uy;\n },\n [random]\n );\n\n const octavedNoise = useCallback(\n (x, octaves, lacunarity, gain, baseAmplitude, baseFrequency, time, seed, baseFlatness) => {\n let y = 0;\n let amplitude = baseAmplitude;\n let frequency = baseFrequency;\n\n for (let i = 0; i < octaves; i++) {\n let octaveAmplitude = amplitude;\n if (i === 0) {\n octaveAmplitude *= baseFlatness;\n }\n y += octaveAmplitude * noise2D(frequency * x + seed * 100, time * frequency * 0.3);\n frequency *= lacunarity;\n amplitude *= gain;\n }\n\n return y;\n },\n [noise2D]\n );\n\n const getCornerPoint = useCallback((centerX, centerY, radius, startAngle, arcLength, progress) => {\n const angle = startAngle + progress * arcLength;\n return {\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n };\n }, []);\n\n const getRoundedRectPoint = useCallback(\n (t, left, top, width, height, radius) => {\n const straightWidth = width - 2 * radius;\n const straightHeight = height - 2 * radius;\n const cornerArc = (Math.PI * radius) / 2;\n const totalPerimeter = 2 * straightWidth + 2 * straightHeight + 4 * cornerArc;\n const distance = t * totalPerimeter;\n\n let accumulated = 0;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + radius + progress * straightWidth, y: top };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + radius, radius, -Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left + width, y: top + radius + progress * straightHeight };\n }\n accumulated += straightHeight;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + height - radius, radius, 0, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + width - radius - progress * straightWidth, y: top + height };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + height - radius, radius, Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left, y: top + height - radius - progress * straightHeight };\n }\n accumulated += straightHeight;\n\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + radius, radius, Math.PI, Math.PI / 2, progress);\n },\n [getCornerPoint]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const octaves = 10;\n const lacunarity = 1.6;\n const gain = 0.7;\n const amplitude = chaos;\n const frequency = 10;\n const baseFlatness = 0;\n const displacement = 60;\n const borderOffset = 60;\n\n const updateSize = () => {\n const rect = container.getBoundingClientRect();\n const width = rect.width + borderOffset * 2;\n const height = rect.height + borderOffset * 2;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n ctx.scale(dpr, dpr);\n\n return { width, height };\n };\n\n let { width, height } = updateSize();\n let lastDpr = Math.min(window.devicePixelRatio || 1, 2);\n\n const drawElectricBorder = currentTime => {\n if (!canvas || !ctx) return;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n if (dpr !== lastDpr) {\n lastDpr = dpr;\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n }\n\n const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000;\n timeRef.current += deltaTime * speed;\n lastFrameTimeRef.current = currentTime;\n\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.scale(dpr, dpr);\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 1;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n const scale = displacement;\n const left = borderOffset;\n const top = borderOffset;\n const borderWidth = width - 2 * borderOffset;\n const borderHeight = height - 2 * borderOffset;\n const maxRadius = Math.min(borderWidth, borderHeight) / 2;\n const radius = Math.min(borderRadius, maxRadius);\n\n const approximatePerimeter = 2 * (borderWidth + borderHeight) + 2 * Math.PI * radius;\n const sampleCount = Math.floor(approximatePerimeter / 2);\n\n ctx.beginPath();\n\n for (let i = 0; i <= sampleCount; i++) {\n const progress = i / sampleCount;\n\n const point = getRoundedRectPoint(progress, left, top, borderWidth, borderHeight, radius);\n\n const xNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 0,\n baseFlatness\n );\n const yNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 1,\n baseFlatness\n );\n\n const displacedX = point.x + xNoise * scale;\n const displacedY = point.y + yNoise * scale;\n\n if (i === 0) {\n ctx.moveTo(displacedX, displacedY);\n } else {\n ctx.lineTo(displacedX, displacedY);\n }\n }\n\n ctx.closePath();\n ctx.stroke();\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n };\n\n const resizeObserver = new ResizeObserver(() => {\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n });\n resizeObserver.observe(container);\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n\n return () => {\n if (animationRef.current) {\n cancelAnimationFrame(animationRef.current);\n }\n resizeObserver.disconnect();\n };\n }, [color, speed, chaos, borderRadius, octavedNoise, getRoundedRectPoint]);\n\n return (\n \n
\n \n
\n
\n \n \n \n
\n
{children}
\n
\n );\n};\n\nexport default ElectricBorder;\n" } ], "registryDependencies": [], diff --git a/public/r/ElectricBorder-TS-CSS.json b/public/r/ElectricBorder-TS-CSS.json index 5a68e5d51..b9832b978 100644 --- a/public/r/ElectricBorder-TS-CSS.json +++ b/public/r/ElectricBorder-TS-CSS.json @@ -13,7 +13,7 @@ { "type": "registry:component", "path": "ElectricBorder/ElectricBorder.tsx", - "content": "import React, { useEffect, useRef, useCallback, CSSProperties, ReactNode } from 'react';\nimport './ElectricBorder.css';\n\ninterface ElectricBorderProps {\n children?: ReactNode;\n color?: string;\n speed?: number;\n chaos?: number;\n borderRadius?: number;\n className?: string;\n style?: CSSProperties;\n}\n\nconst ElectricBorder: React.FC = ({\n children,\n color = '#5227FF',\n speed = 1,\n chaos = 0.12,\n borderRadius = 24,\n className,\n style\n}) => {\n const canvasRef = useRef(null);\n const containerRef = useRef(null);\n const animationRef = useRef(null);\n const timeRef = useRef(0);\n const lastFrameTimeRef = useRef(0);\n\n const random = useCallback((x: number): number => {\n return (Math.sin(x * 12.9898) * 43758.5453) % 1;\n }, []);\n\n const noise2D = useCallback(\n (x: number, y: number): number => {\n const i = Math.floor(x);\n const j = Math.floor(y);\n const fx = x - i;\n const fy = y - j;\n\n const a = random(i + j * 57);\n const b = random(i + 1 + j * 57);\n const c = random(i + (j + 1) * 57);\n const d = random(i + 1 + (j + 1) * 57);\n\n const ux = fx * fx * (3.0 - 2.0 * fx);\n const uy = fy * fy * (3.0 - 2.0 * fy);\n\n return a * (1 - ux) * (1 - uy) + b * ux * (1 - uy) + c * (1 - ux) * uy + d * ux * uy;\n },\n [random]\n );\n\n const octavedNoise = useCallback(\n (\n x: number,\n octaves: number,\n lacunarity: number,\n gain: number,\n baseAmplitude: number,\n baseFrequency: number,\n time: number,\n seed: number,\n baseFlatness: number\n ): number => {\n let y = 0;\n let amplitude = baseAmplitude;\n let frequency = baseFrequency;\n\n for (let i = 0; i < octaves; i++) {\n let octaveAmplitude = amplitude;\n if (i === 0) {\n octaveAmplitude *= baseFlatness;\n }\n y += octaveAmplitude * noise2D(frequency * x + seed * 100, time * frequency * 0.3);\n frequency *= lacunarity;\n amplitude *= gain;\n }\n\n return y;\n },\n [noise2D]\n );\n\n const getCornerPoint = useCallback(\n (\n centerX: number,\n centerY: number,\n radius: number,\n startAngle: number,\n arcLength: number,\n progress: number\n ): { x: number; y: number } => {\n const angle = startAngle + progress * arcLength;\n return {\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n };\n },\n []\n );\n\n const getRoundedRectPoint = useCallback(\n (t: number, left: number, top: number, width: number, height: number, radius: number): { x: number; y: number } => {\n const straightWidth = width - 2 * radius;\n const straightHeight = height - 2 * radius;\n const cornerArc = (Math.PI * radius) / 2;\n const totalPerimeter = 2 * straightWidth + 2 * straightHeight + 4 * cornerArc;\n const distance = t * totalPerimeter;\n\n let accumulated = 0;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + radius + progress * straightWidth, y: top };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + radius, radius, -Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left + width, y: top + radius + progress * straightHeight };\n }\n accumulated += straightHeight;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + height - radius, radius, 0, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + width - radius - progress * straightWidth, y: top + height };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + height - radius, radius, Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left, y: top + height - radius - progress * straightHeight };\n }\n accumulated += straightHeight;\n\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + radius, radius, Math.PI, Math.PI / 2, progress);\n },\n [getCornerPoint]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const octaves = 10;\n const lacunarity = 1.6;\n const gain = 0.7;\n const amplitude = chaos;\n const frequency = 10;\n const baseFlatness = 0;\n const displacement = 60;\n const borderOffset = 60;\n\n const updateSize = () => {\n const rect = container.getBoundingClientRect();\n const width = rect.width + borderOffset * 2;\n const height = rect.height + borderOffset * 2;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n ctx.scale(dpr, dpr);\n\n return { width, height };\n };\n\n let { width, height } = updateSize();\n\n const drawElectricBorder = (currentTime: number) => {\n if (!canvas || !ctx) return;\n\n const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000;\n timeRef.current += deltaTime * speed;\n lastFrameTimeRef.current = currentTime;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.scale(dpr, dpr);\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 1;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n const scale = displacement;\n const left = borderOffset;\n const top = borderOffset;\n const borderWidth = width - 2 * borderOffset;\n const borderHeight = height - 2 * borderOffset;\n const maxRadius = Math.min(borderWidth, borderHeight) / 2;\n const radius = Math.min(borderRadius, maxRadius);\n\n const approximatePerimeter = 2 * (borderWidth + borderHeight) + 2 * Math.PI * radius;\n const sampleCount = Math.floor(approximatePerimeter / 2);\n\n ctx.beginPath();\n\n for (let i = 0; i <= sampleCount; i++) {\n const progress = i / sampleCount;\n\n const point = getRoundedRectPoint(progress, left, top, borderWidth, borderHeight, radius);\n\n const xNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 0,\n baseFlatness\n );\n const yNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 1,\n baseFlatness\n );\n\n const displacedX = point.x + xNoise * scale;\n const displacedY = point.y + yNoise * scale;\n\n if (i === 0) {\n ctx.moveTo(displacedX, displacedY);\n } else {\n ctx.lineTo(displacedX, displacedY);\n }\n }\n\n ctx.closePath();\n ctx.stroke();\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n };\n\n const resizeObserver = new ResizeObserver(() => {\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n });\n resizeObserver.observe(container);\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n\n return () => {\n if (animationRef.current) {\n cancelAnimationFrame(animationRef.current);\n }\n resizeObserver.disconnect();\n };\n }, [color, speed, chaos, borderRadius, octavedNoise, getRoundedRectPoint]);\n\n const vars = {\n '--electric-border-color': color,\n borderRadius\n } as CSSProperties;\n\n return (\n
\n
\n \n
\n
\n
\n
\n
\n
\n
{children}
\n
\n );\n};\n\nexport default ElectricBorder;\n" + "content": "import React, { useEffect, useRef, useCallback, CSSProperties, ReactNode } from 'react';\nimport './ElectricBorder.css';\n\ninterface ElectricBorderProps {\n children?: ReactNode;\n color?: string;\n speed?: number;\n chaos?: number;\n borderRadius?: number;\n className?: string;\n style?: CSSProperties;\n}\n\nconst ElectricBorder: React.FC = ({\n children,\n color = '#5227FF',\n speed = 1,\n chaos = 0.12,\n borderRadius = 24,\n className,\n style\n}) => {\n const canvasRef = useRef(null);\n const containerRef = useRef(null);\n const animationRef = useRef(null);\n const timeRef = useRef(0);\n const lastFrameTimeRef = useRef(0);\n\n const random = useCallback((x: number): number => {\n return (Math.sin(x * 12.9898) * 43758.5453) % 1;\n }, []);\n\n const noise2D = useCallback(\n (x: number, y: number): number => {\n const i = Math.floor(x);\n const j = Math.floor(y);\n const fx = x - i;\n const fy = y - j;\n\n const a = random(i + j * 57);\n const b = random(i + 1 + j * 57);\n const c = random(i + (j + 1) * 57);\n const d = random(i + 1 + (j + 1) * 57);\n\n const ux = fx * fx * (3.0 - 2.0 * fx);\n const uy = fy * fy * (3.0 - 2.0 * fy);\n\n return a * (1 - ux) * (1 - uy) + b * ux * (1 - uy) + c * (1 - ux) * uy + d * ux * uy;\n },\n [random]\n );\n\n const octavedNoise = useCallback(\n (\n x: number,\n octaves: number,\n lacunarity: number,\n gain: number,\n baseAmplitude: number,\n baseFrequency: number,\n time: number,\n seed: number,\n baseFlatness: number\n ): number => {\n let y = 0;\n let amplitude = baseAmplitude;\n let frequency = baseFrequency;\n\n for (let i = 0; i < octaves; i++) {\n let octaveAmplitude = amplitude;\n if (i === 0) {\n octaveAmplitude *= baseFlatness;\n }\n y += octaveAmplitude * noise2D(frequency * x + seed * 100, time * frequency * 0.3);\n frequency *= lacunarity;\n amplitude *= gain;\n }\n\n return y;\n },\n [noise2D]\n );\n\n const getCornerPoint = useCallback(\n (\n centerX: number,\n centerY: number,\n radius: number,\n startAngle: number,\n arcLength: number,\n progress: number\n ): { x: number; y: number } => {\n const angle = startAngle + progress * arcLength;\n return {\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n };\n },\n []\n );\n\n const getRoundedRectPoint = useCallback(\n (t: number, left: number, top: number, width: number, height: number, radius: number): { x: number; y: number } => {\n const straightWidth = width - 2 * radius;\n const straightHeight = height - 2 * radius;\n const cornerArc = (Math.PI * radius) / 2;\n const totalPerimeter = 2 * straightWidth + 2 * straightHeight + 4 * cornerArc;\n const distance = t * totalPerimeter;\n\n let accumulated = 0;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + radius + progress * straightWidth, y: top };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + radius, radius, -Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left + width, y: top + radius + progress * straightHeight };\n }\n accumulated += straightHeight;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + height - radius, radius, 0, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + width - radius - progress * straightWidth, y: top + height };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + height - radius, radius, Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left, y: top + height - radius - progress * straightHeight };\n }\n accumulated += straightHeight;\n\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + radius, radius, Math.PI, Math.PI / 2, progress);\n },\n [getCornerPoint]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const octaves = 10;\n const lacunarity = 1.6;\n const gain = 0.7;\n const amplitude = chaos;\n const frequency = 10;\n const baseFlatness = 0;\n const displacement = 60;\n const borderOffset = 60;\n\n const updateSize = () => {\n const rect = container.getBoundingClientRect();\n const width = rect.width + borderOffset * 2;\n const height = rect.height + borderOffset * 2;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n ctx.scale(dpr, dpr);\n\n return { width, height };\n };\n\n let { width, height } = updateSize();\n let lastDpr = Math.min(window.devicePixelRatio || 1, 2);\n\n const drawElectricBorder = (currentTime: number) => {\n if (!canvas || !ctx) return;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n if (dpr !== lastDpr) {\n lastDpr = dpr;\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n }\n\n const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000;\n timeRef.current += deltaTime * speed;\n lastFrameTimeRef.current = currentTime;\n\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.scale(dpr, dpr);\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 1;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n const scale = displacement;\n const left = borderOffset;\n const top = borderOffset;\n const borderWidth = width - 2 * borderOffset;\n const borderHeight = height - 2 * borderOffset;\n const maxRadius = Math.min(borderWidth, borderHeight) / 2;\n const radius = Math.min(borderRadius, maxRadius);\n\n const approximatePerimeter = 2 * (borderWidth + borderHeight) + 2 * Math.PI * radius;\n const sampleCount = Math.floor(approximatePerimeter / 2);\n\n ctx.beginPath();\n\n for (let i = 0; i <= sampleCount; i++) {\n const progress = i / sampleCount;\n\n const point = getRoundedRectPoint(progress, left, top, borderWidth, borderHeight, radius);\n\n const xNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 0,\n baseFlatness\n );\n const yNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 1,\n baseFlatness\n );\n\n const displacedX = point.x + xNoise * scale;\n const displacedY = point.y + yNoise * scale;\n\n if (i === 0) {\n ctx.moveTo(displacedX, displacedY);\n } else {\n ctx.lineTo(displacedX, displacedY);\n }\n }\n\n ctx.closePath();\n ctx.stroke();\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n };\n\n const resizeObserver = new ResizeObserver(() => {\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n });\n resizeObserver.observe(container);\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n\n return () => {\n if (animationRef.current) {\n cancelAnimationFrame(animationRef.current);\n }\n resizeObserver.disconnect();\n };\n }, [color, speed, chaos, borderRadius, octavedNoise, getRoundedRectPoint]);\n\n const vars = {\n '--electric-border-color': color,\n borderRadius\n } as CSSProperties;\n\n return (\n
\n
\n \n
\n
\n
\n
\n
\n
\n
{children}
\n
\n );\n};\n\nexport default ElectricBorder;\n" } ], "registryDependencies": [], diff --git a/public/r/ElectricBorder-TS-TW.json b/public/r/ElectricBorder-TS-TW.json index 6a58f20a5..c0ceeac3a 100644 --- a/public/r/ElectricBorder-TS-TW.json +++ b/public/r/ElectricBorder-TS-TW.json @@ -8,7 +8,7 @@ { "type": "registry:component", "path": "ElectricBorder/ElectricBorder.tsx", - "content": "import React, { useEffect, useRef, useCallback, CSSProperties, ReactNode } from 'react';\n\nfunction hexToRgba(hex: string, alpha: number = 1): string {\n if (!hex) return `rgba(0,0,0,${alpha})`;\n let h = hex.replace('#', '');\n if (h.length === 3) {\n h = h\n .split('')\n .map(c => c + c)\n .join('');\n }\n const int = parseInt(h, 16);\n const r = (int >> 16) & 255;\n const g = (int >> 8) & 255;\n const b = int & 255;\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\ninterface ElectricBorderProps {\n children?: ReactNode;\n color?: string;\n speed?: number;\n chaos?: number;\n borderRadius?: number;\n className?: string;\n style?: CSSProperties;\n}\n\nconst ElectricBorder: React.FC = ({\n children,\n color = '#5227FF',\n speed = 1,\n chaos = 0.12,\n borderRadius = 24,\n className,\n style\n}) => {\n const canvasRef = useRef(null);\n const containerRef = useRef(null);\n const animationRef = useRef(null);\n const timeRef = useRef(0);\n const lastFrameTimeRef = useRef(0);\n\n const random = useCallback((x: number): number => {\n return (Math.sin(x * 12.9898) * 43758.5453) % 1;\n }, []);\n\n const noise2D = useCallback(\n (x: number, y: number): number => {\n const i = Math.floor(x);\n const j = Math.floor(y);\n const fx = x - i;\n const fy = y - j;\n\n const a = random(i + j * 57);\n const b = random(i + 1 + j * 57);\n const c = random(i + (j + 1) * 57);\n const d = random(i + 1 + (j + 1) * 57);\n\n const ux = fx * fx * (3.0 - 2.0 * fx);\n const uy = fy * fy * (3.0 - 2.0 * fy);\n\n return a * (1 - ux) * (1 - uy) + b * ux * (1 - uy) + c * (1 - ux) * uy + d * ux * uy;\n },\n [random]\n );\n\n const octavedNoise = useCallback(\n (\n x: number,\n octaves: number,\n lacunarity: number,\n gain: number,\n baseAmplitude: number,\n baseFrequency: number,\n time: number,\n seed: number,\n baseFlatness: number\n ): number => {\n let y = 0;\n let amplitude = baseAmplitude;\n let frequency = baseFrequency;\n\n for (let i = 0; i < octaves; i++) {\n let octaveAmplitude = amplitude;\n if (i === 0) {\n octaveAmplitude *= baseFlatness;\n }\n y += octaveAmplitude * noise2D(frequency * x + seed * 100, time * frequency * 0.3);\n frequency *= lacunarity;\n amplitude *= gain;\n }\n\n return y;\n },\n [noise2D]\n );\n\n const getCornerPoint = useCallback(\n (\n centerX: number,\n centerY: number,\n radius: number,\n startAngle: number,\n arcLength: number,\n progress: number\n ): { x: number; y: number } => {\n const angle = startAngle + progress * arcLength;\n return {\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n };\n },\n []\n );\n\n const getRoundedRectPoint = useCallback(\n (t: number, left: number, top: number, width: number, height: number, radius: number): { x: number; y: number } => {\n const straightWidth = width - 2 * radius;\n const straightHeight = height - 2 * radius;\n const cornerArc = (Math.PI * radius) / 2;\n const totalPerimeter = 2 * straightWidth + 2 * straightHeight + 4 * cornerArc;\n const distance = t * totalPerimeter;\n\n let accumulated = 0;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + radius + progress * straightWidth, y: top };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + radius, radius, -Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left + width, y: top + radius + progress * straightHeight };\n }\n accumulated += straightHeight;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + height - radius, radius, 0, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + width - radius - progress * straightWidth, y: top + height };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + height - radius, radius, Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left, y: top + height - radius - progress * straightHeight };\n }\n accumulated += straightHeight;\n\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + radius, radius, Math.PI, Math.PI / 2, progress);\n },\n [getCornerPoint]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const octaves = 10;\n const lacunarity = 1.6;\n const gain = 0.7;\n const amplitude = chaos;\n const frequency = 10;\n const baseFlatness = 0;\n const displacement = 60;\n const borderOffset = 60;\n\n const updateSize = () => {\n const rect = container.getBoundingClientRect();\n const width = rect.width + borderOffset * 2;\n const height = rect.height + borderOffset * 2;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n ctx.scale(dpr, dpr);\n\n return { width, height };\n };\n\n let { width, height } = updateSize();\n\n const drawElectricBorder = (currentTime: number) => {\n if (!canvas || !ctx) return;\n\n const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000;\n timeRef.current += deltaTime * speed;\n lastFrameTimeRef.current = currentTime;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.scale(dpr, dpr);\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 1;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n const scale = displacement;\n const left = borderOffset;\n const top = borderOffset;\n const borderWidth = width - 2 * borderOffset;\n const borderHeight = height - 2 * borderOffset;\n const maxRadius = Math.min(borderWidth, borderHeight) / 2;\n const radius = Math.min(borderRadius, maxRadius);\n\n const approximatePerimeter = 2 * (borderWidth + borderHeight) + 2 * Math.PI * radius;\n const sampleCount = Math.floor(approximatePerimeter / 2);\n\n ctx.beginPath();\n\n for (let i = 0; i <= sampleCount; i++) {\n const progress = i / sampleCount;\n\n const point = getRoundedRectPoint(progress, left, top, borderWidth, borderHeight, radius);\n\n const xNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 0,\n baseFlatness\n );\n const yNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 1,\n baseFlatness\n );\n\n const displacedX = point.x + xNoise * scale;\n const displacedY = point.y + yNoise * scale;\n\n if (i === 0) {\n ctx.moveTo(displacedX, displacedY);\n } else {\n ctx.lineTo(displacedX, displacedY);\n }\n }\n\n ctx.closePath();\n ctx.stroke();\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n };\n\n const resizeObserver = new ResizeObserver(() => {\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n });\n resizeObserver.observe(container);\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n\n return () => {\n if (animationRef.current) {\n cancelAnimationFrame(animationRef.current);\n }\n resizeObserver.disconnect();\n };\n }, [color, speed, chaos, borderRadius, octavedNoise, getRoundedRectPoint]);\n\n return (\n \n
\n \n
\n
\n \n \n \n
\n
{children}
\n
\n );\n};\n\nexport default ElectricBorder;\n" + "content": "import React, { useEffect, useRef, useCallback, CSSProperties, ReactNode } from 'react';\n\nfunction hexToRgba(hex: string, alpha: number = 1): string {\n if (!hex) return `rgba(0,0,0,${alpha})`;\n let h = hex.replace('#', '');\n if (h.length === 3) {\n h = h\n .split('')\n .map(c => c + c)\n .join('');\n }\n const int = parseInt(h, 16);\n const r = (int >> 16) & 255;\n const g = (int >> 8) & 255;\n const b = int & 255;\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\ninterface ElectricBorderProps {\n children?: ReactNode;\n color?: string;\n speed?: number;\n chaos?: number;\n borderRadius?: number;\n className?: string;\n style?: CSSProperties;\n}\n\nconst ElectricBorder: React.FC = ({\n children,\n color = '#5227FF',\n speed = 1,\n chaos = 0.12,\n borderRadius = 24,\n className,\n style\n}) => {\n const canvasRef = useRef(null);\n const containerRef = useRef(null);\n const animationRef = useRef(null);\n const timeRef = useRef(0);\n const lastFrameTimeRef = useRef(0);\n\n const random = useCallback((x: number): number => {\n return (Math.sin(x * 12.9898) * 43758.5453) % 1;\n }, []);\n\n const noise2D = useCallback(\n (x: number, y: number): number => {\n const i = Math.floor(x);\n const j = Math.floor(y);\n const fx = x - i;\n const fy = y - j;\n\n const a = random(i + j * 57);\n const b = random(i + 1 + j * 57);\n const c = random(i + (j + 1) * 57);\n const d = random(i + 1 + (j + 1) * 57);\n\n const ux = fx * fx * (3.0 - 2.0 * fx);\n const uy = fy * fy * (3.0 - 2.0 * fy);\n\n return a * (1 - ux) * (1 - uy) + b * ux * (1 - uy) + c * (1 - ux) * uy + d * ux * uy;\n },\n [random]\n );\n\n const octavedNoise = useCallback(\n (\n x: number,\n octaves: number,\n lacunarity: number,\n gain: number,\n baseAmplitude: number,\n baseFrequency: number,\n time: number,\n seed: number,\n baseFlatness: number\n ): number => {\n let y = 0;\n let amplitude = baseAmplitude;\n let frequency = baseFrequency;\n\n for (let i = 0; i < octaves; i++) {\n let octaveAmplitude = amplitude;\n if (i === 0) {\n octaveAmplitude *= baseFlatness;\n }\n y += octaveAmplitude * noise2D(frequency * x + seed * 100, time * frequency * 0.3);\n frequency *= lacunarity;\n amplitude *= gain;\n }\n\n return y;\n },\n [noise2D]\n );\n\n const getCornerPoint = useCallback(\n (\n centerX: number,\n centerY: number,\n radius: number,\n startAngle: number,\n arcLength: number,\n progress: number\n ): { x: number; y: number } => {\n const angle = startAngle + progress * arcLength;\n return {\n x: centerX + radius * Math.cos(angle),\n y: centerY + radius * Math.sin(angle)\n };\n },\n []\n );\n\n const getRoundedRectPoint = useCallback(\n (t: number, left: number, top: number, width: number, height: number, radius: number): { x: number; y: number } => {\n const straightWidth = width - 2 * radius;\n const straightHeight = height - 2 * radius;\n const cornerArc = (Math.PI * radius) / 2;\n const totalPerimeter = 2 * straightWidth + 2 * straightHeight + 4 * cornerArc;\n const distance = t * totalPerimeter;\n\n let accumulated = 0;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + radius + progress * straightWidth, y: top };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + radius, radius, -Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left + width, y: top + radius + progress * straightHeight };\n }\n accumulated += straightHeight;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + width - radius, top + height - radius, radius, 0, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightWidth) {\n const progress = (distance - accumulated) / straightWidth;\n return { x: left + width - radius - progress * straightWidth, y: top + height };\n }\n accumulated += straightWidth;\n\n if (distance <= accumulated + cornerArc) {\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + height - radius, radius, Math.PI / 2, Math.PI / 2, progress);\n }\n accumulated += cornerArc;\n\n if (distance <= accumulated + straightHeight) {\n const progress = (distance - accumulated) / straightHeight;\n return { x: left, y: top + height - radius - progress * straightHeight };\n }\n accumulated += straightHeight;\n\n const progress = (distance - accumulated) / cornerArc;\n return getCornerPoint(left + radius, top + radius, radius, Math.PI, Math.PI / 2, progress);\n },\n [getCornerPoint]\n );\n\n useEffect(() => {\n const canvas = canvasRef.current;\n const container = containerRef.current;\n if (!canvas || !container) return;\n\n const ctx = canvas.getContext('2d');\n if (!ctx) return;\n\n const octaves = 10;\n const lacunarity = 1.6;\n const gain = 0.7;\n const amplitude = chaos;\n const frequency = 10;\n const baseFlatness = 0;\n const displacement = 60;\n const borderOffset = 60;\n\n const updateSize = () => {\n const rect = container.getBoundingClientRect();\n const width = rect.width + borderOffset * 2;\n const height = rect.height + borderOffset * 2;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n canvas.width = width * dpr;\n canvas.height = height * dpr;\n canvas.style.width = `${width}px`;\n canvas.style.height = `${height}px`;\n ctx.scale(dpr, dpr);\n\n return { width, height };\n };\n\n let { width, height } = updateSize();\n let lastDpr = Math.min(window.devicePixelRatio || 1, 2);\n\n const drawElectricBorder = (currentTime: number) => {\n if (!canvas || !ctx) return;\n\n const dpr = Math.min(window.devicePixelRatio || 1, 2);\n if (dpr !== lastDpr) {\n lastDpr = dpr;\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n }\n\n const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000;\n timeRef.current += deltaTime * speed;\n lastFrameTimeRef.current = currentTime;\n\n ctx.setTransform(1, 0, 0, 1, 0, 0);\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n ctx.scale(dpr, dpr);\n\n ctx.strokeStyle = color;\n ctx.lineWidth = 1;\n ctx.lineCap = 'round';\n ctx.lineJoin = 'round';\n\n const scale = displacement;\n const left = borderOffset;\n const top = borderOffset;\n const borderWidth = width - 2 * borderOffset;\n const borderHeight = height - 2 * borderOffset;\n const maxRadius = Math.min(borderWidth, borderHeight) / 2;\n const radius = Math.min(borderRadius, maxRadius);\n\n const approximatePerimeter = 2 * (borderWidth + borderHeight) + 2 * Math.PI * radius;\n const sampleCount = Math.floor(approximatePerimeter / 2);\n\n ctx.beginPath();\n\n for (let i = 0; i <= sampleCount; i++) {\n const progress = i / sampleCount;\n\n const point = getRoundedRectPoint(progress, left, top, borderWidth, borderHeight, radius);\n\n const xNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 0,\n baseFlatness\n );\n const yNoise = octavedNoise(\n progress * 8,\n octaves,\n lacunarity,\n gain,\n amplitude,\n frequency,\n timeRef.current,\n 1,\n baseFlatness\n );\n\n const displacedX = point.x + xNoise * scale;\n const displacedY = point.y + yNoise * scale;\n\n if (i === 0) {\n ctx.moveTo(displacedX, displacedY);\n } else {\n ctx.lineTo(displacedX, displacedY);\n }\n }\n\n ctx.closePath();\n ctx.stroke();\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n };\n\n const resizeObserver = new ResizeObserver(() => {\n const newSize = updateSize();\n width = newSize.width;\n height = newSize.height;\n });\n resizeObserver.observe(container);\n\n animationRef.current = requestAnimationFrame(drawElectricBorder);\n\n return () => {\n if (animationRef.current) {\n cancelAnimationFrame(animationRef.current);\n }\n resizeObserver.disconnect();\n };\n }, [color, speed, chaos, borderRadius, octavedNoise, getRoundedRectPoint]);\n\n return (\n \n
\n \n
\n
\n \n \n \n
\n
{children}
\n
\n );\n};\n\nexport default ElectricBorder;\n" } ], "registryDependencies": [], diff --git a/src/content/Animations/ElectricBorder/ElectricBorder.jsx b/src/content/Animations/ElectricBorder/ElectricBorder.jsx index 5dcdb69dd..7394a57b6 100644 --- a/src/content/Animations/ElectricBorder/ElectricBorder.jsx +++ b/src/content/Animations/ElectricBorder/ElectricBorder.jsx @@ -171,16 +171,23 @@ const ElectricBorder = ({ }; let { width, height } = updateSize(); + let lastDpr = Math.min(window.devicePixelRatio || 1, 2); const drawElectricBorder = currentTime => { if (!canvas || !ctx) return; + const dpr = Math.min(window.devicePixelRatio || 1, 2); + if (dpr !== lastDpr) { + lastDpr = dpr; + const newSize = updateSize(); + width = newSize.width; + height = newSize.height; + } + const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000; timeRef.current += deltaTime * speed; lastFrameTimeRef.current = currentTime; - // Clear canvas - const dpr = Math.min(window.devicePixelRatio || 1, 2); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.scale(dpr, dpr); diff --git a/src/tailwind/Animations/ElectricBorder/ElectricBorder.jsx b/src/tailwind/Animations/ElectricBorder/ElectricBorder.jsx index f59de3414..6b1c16333 100644 --- a/src/tailwind/Animations/ElectricBorder/ElectricBorder.jsx +++ b/src/tailwind/Animations/ElectricBorder/ElectricBorder.jsx @@ -175,15 +175,23 @@ const ElectricBorder = ({ }; let { width, height } = updateSize(); + let lastDpr = Math.min(window.devicePixelRatio || 1, 2); const drawElectricBorder = currentTime => { if (!canvas || !ctx) return; + const dpr = Math.min(window.devicePixelRatio || 1, 2); + if (dpr !== lastDpr) { + lastDpr = dpr; + const newSize = updateSize(); + width = newSize.width; + height = newSize.height; + } + const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000; timeRef.current += deltaTime * speed; lastFrameTimeRef.current = currentTime; - const dpr = Math.min(window.devicePixelRatio || 1, 2); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.scale(dpr, dpr); diff --git a/src/ts-default/Animations/ElectricBorder/ElectricBorder.tsx b/src/ts-default/Animations/ElectricBorder/ElectricBorder.tsx index 31261eb77..ab72ca53f 100644 --- a/src/ts-default/Animations/ElectricBorder/ElectricBorder.tsx +++ b/src/ts-default/Animations/ElectricBorder/ElectricBorder.tsx @@ -190,15 +190,23 @@ const ElectricBorder: React.FC = ({ }; let { width, height } = updateSize(); + let lastDpr = Math.min(window.devicePixelRatio || 1, 2); const drawElectricBorder = (currentTime: number) => { if (!canvas || !ctx) return; + const dpr = Math.min(window.devicePixelRatio || 1, 2); + if (dpr !== lastDpr) { + lastDpr = dpr; + const newSize = updateSize(); + width = newSize.width; + height = newSize.height; + } + const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000; timeRef.current += deltaTime * speed; lastFrameTimeRef.current = currentTime; - const dpr = Math.min(window.devicePixelRatio || 1, 2); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.scale(dpr, dpr); diff --git a/src/ts-tailwind/Animations/ElectricBorder/ElectricBorder.tsx b/src/ts-tailwind/Animations/ElectricBorder/ElectricBorder.tsx index 47c297db8..b9b31451a 100644 --- a/src/ts-tailwind/Animations/ElectricBorder/ElectricBorder.tsx +++ b/src/ts-tailwind/Animations/ElectricBorder/ElectricBorder.tsx @@ -205,15 +205,23 @@ const ElectricBorder: React.FC = ({ }; let { width, height } = updateSize(); + let lastDpr = Math.min(window.devicePixelRatio || 1, 2); const drawElectricBorder = (currentTime: number) => { if (!canvas || !ctx) return; + const dpr = Math.min(window.devicePixelRatio || 1, 2); + if (dpr !== lastDpr) { + lastDpr = dpr; + const newSize = updateSize(); + width = newSize.width; + height = newSize.height; + } + const deltaTime = (currentTime - lastFrameTimeRef.current) / 1000; timeRef.current += deltaTime * speed; lastFrameTimeRef.current = currentTime; - const dpr = Math.min(window.devicePixelRatio || 1, 2); ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.scale(dpr, dpr);