diff --git a/public/r/OrbitImages-JS-CSS.json b/public/r/OrbitImages-JS-CSS.json index 7fded94fc..67e9855b8 100644 --- a/public/r/OrbitImages-JS-CSS.json +++ b/public/r/OrbitImages-JS-CSS.json @@ -8,12 +8,12 @@ { "type": "registry:component", "path": "OrbitImages/OrbitImages.css", - "content": ".orbit-container {\n position: relative;\n margin-left: auto;\n margin-right: auto;\n}\n\n.orbit-scaling-container {\n width: 100%;\n height: 100%;\n position: relative;\n}\n\n.orbit-scaling-container--responsive {\n position: absolute;\n left: 50%;\n top: 50%;\n transform-origin: center center;\n}\n\n.orbit-rotation-wrapper {\n width: 100%;\n height: 100%;\n transform-origin: center center;\n position: relative;\n}\n\n.orbit-path-svg {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n\n.orbit-item {\n position: absolute;\n will-change: transform;\n user-select: none;\n}\n\n.orbit-center-content {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n}\n\n.orbit-image {\n width: 100%;\n height: 100%;\n object-fit: contain;\n}\n" + "content": ".orbit-container {\r\n position: relative;\r\n margin-left: auto;\r\n margin-right: auto;\r\n}\r\n\r\n.orbit-scaling-container {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n}\r\n\r\n.orbit-scaling-container--responsive {\r\n position: absolute;\r\n left: 50%;\r\n top: 50%;\r\n transform-origin: center center;\r\n}\r\n\r\n.orbit-rotation-wrapper {\r\n width: 100%;\r\n height: 100%;\r\n transform-origin: center center;\r\n position: relative;\r\n}\r\n\r\n.orbit-path-svg {\r\n position: absolute;\r\n inset: 0;\r\n pointer-events: none;\r\n}\r\n\r\n.orbit-item {\r\n position: absolute;\r\n will-change: transform;\r\n user-select: none;\r\n}\r\n\r\n.orbit-center-content {\r\n position: absolute;\r\n inset: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 10;\r\n}\r\n\r\n.orbit-image {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: contain;\r\n}\r\n" }, { "type": "registry:component", "path": "OrbitImages/OrbitImages.jsx", - "content": "// Component created by Dominik Koch\n// https://x.com/dominikkoch\n\nimport { useMemo, useEffect, useRef, useState } from 'react';\nimport { motion, useMotionValue, useTransform, animate } from 'motion/react';\nimport './OrbitImages.css';\n\nfunction generateEllipsePath(cx, cy, rx, ry) {\n return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;\n}\n\nfunction generateCirclePath(cx, cy, r) {\n return generateEllipsePath(cx, cy, r, r);\n}\n\nfunction generateSquarePath(cx, cy, size) {\n const h = size / 2;\n return `M ${cx - h} ${cy - h} L ${cx + h} ${cy - h} L ${cx + h} ${cy + h} L ${cx - h} ${cy + h} Z`;\n}\n\nfunction generateRectanglePath(cx, cy, w, h) {\n const hw = w / 2;\n const hh = h / 2;\n return `M ${cx - hw} ${cy - hh} L ${cx + hw} ${cy - hh} L ${cx + hw} ${cy + hh} L ${cx - hw} ${cy + hh} Z`;\n}\n\nfunction generateTrianglePath(cx, cy, size) {\n const height = (size * Math.sqrt(3)) / 2;\n const hs = size / 2;\n return `M ${cx} ${cy - height / 1.5} L ${cx + hs} ${cy + height / 3} L ${cx - hs} ${cy + height / 3} Z`;\n}\n\nfunction generateStarPath(cx, cy, outerR, innerR, points) {\n const step = Math.PI / points;\n let path = '';\n for (let i = 0; i < 2 * points; i++) {\n const r = i % 2 === 0 ? outerR : innerR;\n const angle = i * step - Math.PI / 2;\n const x = cx + r * Math.cos(angle);\n const y = cy + r * Math.sin(angle);\n path += i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`;\n }\n return path + ' Z';\n}\n\nfunction generateHeartPath(cx, cy, size) {\n const s = size / 30;\n return `M ${cx} ${cy + 12 * s} C ${cx - 20 * s} ${cy - 5 * s}, ${cx - 12 * s} ${cy - 18 * s}, ${cx} ${cy - 8 * s} C ${cx + 12 * s} ${cy - 18 * s}, ${cx + 20 * s} ${cy - 5 * s}, ${cx} ${cy + 12 * s}`;\n}\n\nfunction generateInfinityPath(cx, cy, w, h) {\n const hw = w / 2;\n const hh = h / 2;\n return `M ${cx} ${cy} C ${cx + hw * 0.5} ${cy - hh}, ${cx + hw} ${cy - hh}, ${cx + hw} ${cy} C ${cx + hw} ${cy + hh}, ${cx + hw * 0.5} ${cy + hh}, ${cx} ${cy} C ${cx - hw * 0.5} ${cy + hh}, ${cx - hw} ${cy + hh}, ${cx - hw} ${cy} C ${cx - hw} ${cy - hh}, ${cx - hw * 0.5} ${cy - hh}, ${cx} ${cy}`;\n}\n\nfunction generateWavePath(cx, cy, w, amplitude, waves) {\n const pts = [];\n const segs = waves * 20;\n const hw = w / 2;\n for (let i = 0; i <= segs; i++) {\n const x = cx - hw + (w * i) / segs;\n const y = cy + Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\n pts.push(i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`);\n }\n for (let i = segs; i >= 0; i--) {\n const x = cx - hw + (w * i) / segs;\n const y = cy - Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\n pts.push(`L ${x} ${y}`);\n }\n return pts.join(' ') + ' Z';\n}\n\nfunction OrbitItem({ item, index, totalItems, path, itemSize, rotation, progress, fill }) {\n const itemOffset = fill ? (index / totalItems) * 100 : 0;\n\n const offsetDistance = useTransform(progress, (p) => {\n const offset = (((p + itemOffset) % 100) + 100) % 100;\n return `${offset}%`;\n });\n\n return (\n \n
{item}
\n \n );\n}\n\nexport default function OrbitImages({\n images = [],\n altPrefix = 'Orbiting image',\n shape = 'ellipse',\n customPath,\n baseWidth = 1400,\n radiusX = 700,\n radiusY = 170,\n radius = 300,\n starPoints = 5,\n starInnerRatio = 0.5,\n rotation = -8,\n duration = 40,\n itemSize = 64,\n direction = 'normal',\n fill = true,\n width = 100,\n height = 100,\n className = '',\n showPath = false,\n pathColor = 'rgba(0,0,0,0.1)',\n pathWidth = 2,\n easing = 'linear',\n paused = false,\n centerContent,\n responsive = false,\n}) {\n const containerRef = useRef(null);\n const [scale, setScale] = useState(1);\n\n const designCenterX = baseWidth / 2;\n const designCenterY = baseWidth / 2;\n\n const path = useMemo(() => {\n switch (shape) {\n case 'circle':\n return generateCirclePath(designCenterX, designCenterY, radius);\n case 'ellipse':\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\n case 'square':\n return generateSquarePath(designCenterX, designCenterY, radius * 2);\n case 'rectangle':\n return generateRectanglePath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\n case 'triangle':\n return generateTrianglePath(designCenterX, designCenterY, radius * 2);\n case 'star':\n return generateStarPath(designCenterX, designCenterY, radius, radius * starInnerRatio, starPoints);\n case 'heart':\n return generateHeartPath(designCenterX, designCenterY, radius * 2);\n case 'infinity':\n return generateInfinityPath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\n case 'wave':\n return generateWavePath(designCenterX, designCenterY, radiusX * 2, radiusY, 3);\n case 'custom':\n return customPath || generateCirclePath(designCenterX, designCenterY, radius);\n default:\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\n }\n }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]);\n\n useEffect(() => {\n if (!responsive || !containerRef.current) return;\n const updateScale = () => {\n if (!containerRef.current) return;\n setScale(containerRef.current.clientWidth / baseWidth);\n };\n updateScale();\n const observer = new ResizeObserver(updateScale);\n observer.observe(containerRef.current);\n return () => observer.disconnect();\n }, [responsive, baseWidth]);\n\n const progress = useMotionValue(0);\n\n useEffect(() => {\n if (paused) return;\n const controls = animate(progress, direction === 'reverse' ? -100 : 100, {\n duration,\n ease: easing,\n repeat: Infinity,\n repeatType: 'loop',\n });\n return () => controls.stop();\n }, [progress, duration, easing, direction, paused]);\n\n const containerWidth = responsive ? '100%' : (typeof width === 'number' ? width : '100%');\n const containerHeight = responsive ? 'auto' : (typeof height === 'number' ? height : (typeof width === 'number' ? width : 'auto'));\n\n const items = images.map((src, index) => (\n \n ));\n\n return (\n \n \n \n {showPath && (\n \n \n \n )}\n\n {items.map((item, index) => (\n \n ))}\n \n \n\n {centerContent && (\n
\n {centerContent}\n
\n )}\n \n );\n}\n" + "content": "// Component created by Dominik Koch\r\n// https://x.com/dominikkoch\r\n\r\nimport { useMemo, useEffect, useLayoutEffect, useRef, useState } from 'react';\r\nimport { motion, useMotionValue, useTransform, animate } from 'motion/react';\r\nimport './OrbitImages.css';\r\n\r\nfunction generateEllipsePath(cx, cy, rx, ry) {\r\n return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;\r\n}\r\n\r\nfunction generateCirclePath(cx, cy, r) {\r\n return generateEllipsePath(cx, cy, r, r);\r\n}\r\n\r\nfunction generateSquarePath(cx, cy, size) {\r\n const h = size / 2;\r\n return `M ${cx - h} ${cy - h} L ${cx + h} ${cy - h} L ${cx + h} ${cy + h} L ${cx - h} ${cy + h} Z`;\r\n}\r\n\r\nfunction generateRectanglePath(cx, cy, w, h) {\r\n const hw = w / 2;\r\n const hh = h / 2;\r\n return `M ${cx - hw} ${cy - hh} L ${cx + hw} ${cy - hh} L ${cx + hw} ${cy + hh} L ${cx - hw} ${cy + hh} Z`;\r\n}\r\n\r\nfunction generateTrianglePath(cx, cy, size) {\r\n const height = (size * Math.sqrt(3)) / 2;\r\n const hs = size / 2;\r\n return `M ${cx} ${cy - height / 1.5} L ${cx + hs} ${cy + height / 3} L ${cx - hs} ${cy + height / 3} Z`;\r\n}\r\n\r\nfunction generateStarPath(cx, cy, outerR, innerR, points) {\r\n const step = Math.PI / points;\r\n let path = '';\r\n for (let i = 0; i < 2 * points; i++) {\r\n const r = i % 2 === 0 ? outerR : innerR;\r\n const angle = i * step - Math.PI / 2;\r\n const x = cx + r * Math.cos(angle);\r\n const y = cy + r * Math.sin(angle);\r\n path += i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`;\r\n }\r\n return path + ' Z';\r\n}\r\n\r\nfunction generateHeartPath(cx, cy, size) {\r\n const s = size / 30;\r\n return `M ${cx} ${cy + 12 * s} C ${cx - 20 * s} ${cy - 5 * s}, ${cx - 12 * s} ${cy - 18 * s}, ${cx} ${cy - 8 * s} C ${cx + 12 * s} ${cy - 18 * s}, ${cx + 20 * s} ${cy - 5 * s}, ${cx} ${cy + 12 * s}`;\r\n}\r\n\r\nfunction generateInfinityPath(cx, cy, w, h) {\r\n const hw = w / 2;\r\n const hh = h / 2;\r\n return `M ${cx} ${cy} C ${cx + hw * 0.5} ${cy - hh}, ${cx + hw} ${cy - hh}, ${cx + hw} ${cy} C ${cx + hw} ${cy + hh}, ${cx + hw * 0.5} ${cy + hh}, ${cx} ${cy} C ${cx - hw * 0.5} ${cy + hh}, ${cx - hw} ${cy + hh}, ${cx - hw} ${cy} C ${cx - hw} ${cy - hh}, ${cx - hw * 0.5} ${cy - hh}, ${cx} ${cy}`;\r\n}\r\n\r\nfunction generateWavePath(cx, cy, w, amplitude, waves) {\r\n const pts = [];\r\n const segs = waves * 20;\r\n const hw = w / 2;\r\n for (let i = 0; i <= segs; i++) {\r\n const x = cx - hw + (w * i) / segs;\r\n const y = cy + Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\r\n pts.push(i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`);\r\n }\r\n for (let i = segs; i >= 0; i--) {\r\n const x = cx - hw + (w * i) / segs;\r\n const y = cy - Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\r\n pts.push(`L ${x} ${y}`);\r\n }\r\n return pts.join(' ') + ' Z';\r\n}\r\n\r\nfunction OrbitItem({ item, index, totalItems, path, itemSize, rotation, progress, fill }) {\r\n const itemOffset = fill ? (index / totalItems) * 100 : 0;\r\n\r\n const offsetDistance = useTransform(progress, (p) => {\r\n const offset = (((p + itemOffset) % 100) + 100) % 100;\r\n return `${offset}%`;\r\n });\r\n\r\n return (\r\n \r\n
{item}
\r\n \r\n );\r\n}\r\n\r\nexport default function OrbitImages({\r\n images = [],\r\n altPrefix = 'Orbiting image',\r\n shape = 'ellipse',\r\n customPath,\r\n baseWidth = 1400,\r\n radiusX = 700,\r\n radiusY = 170,\r\n radius = 300,\r\n starPoints = 5,\r\n starInnerRatio = 0.5,\r\n rotation = -8,\r\n duration = 40,\r\n itemSize = 64,\r\n direction = 'normal',\r\n fill = true,\r\n width = 100,\r\n height = 100,\r\n className = '',\r\n showPath = false,\r\n pathColor = 'rgba(0,0,0,0.1)',\r\n pathWidth = 2,\r\n easing = 'linear',\r\n paused = false,\r\n centerContent,\r\n responsive = false,\r\n}) {\r\n const containerRef = useRef(null);\r\n const [scale, setScale] = useState(null);\r\n\r\n const designCenterX = baseWidth / 2;\r\n const designCenterY = baseWidth / 2;\r\n\r\n const path = useMemo(() => {\r\n switch (shape) {\r\n case 'circle':\r\n return generateCirclePath(designCenterX, designCenterY, radius);\r\n case 'ellipse':\r\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\r\n case 'square':\r\n return generateSquarePath(designCenterX, designCenterY, radius * 2);\r\n case 'rectangle':\r\n return generateRectanglePath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\r\n case 'triangle':\r\n return generateTrianglePath(designCenterX, designCenterY, radius * 2);\r\n case 'star':\r\n return generateStarPath(designCenterX, designCenterY, radius, radius * starInnerRatio, starPoints);\r\n case 'heart':\r\n return generateHeartPath(designCenterX, designCenterY, radius * 2);\r\n case 'infinity':\r\n return generateInfinityPath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\r\n case 'wave':\r\n return generateWavePath(designCenterX, designCenterY, radiusX * 2, radiusY, 3);\r\n case 'custom':\r\n return customPath || generateCirclePath(designCenterX, designCenterY, radius);\r\n default:\r\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\r\n }\r\n }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]);\r\n\r\n useLayoutEffect(() => {\r\n if (!responsive || !containerRef.current) return;\r\n const updateScale = () => {\r\n if (!containerRef.current) return;\r\n setScale(containerRef.current.clientWidth / baseWidth);\r\n };\r\n updateScale();\r\n const observer = new ResizeObserver(updateScale);\r\n observer.observe(containerRef.current);\r\n return () => observer.disconnect();\r\n }, [responsive, baseWidth]);\r\n\r\n const progress = useMotionValue(0);\r\n\r\n useEffect(() => {\r\n if (paused) return;\r\n const controls = animate(progress, direction === 'reverse' ? -100 : 100, {\r\n duration,\r\n ease: easing,\r\n repeat: Infinity,\r\n repeatType: 'loop',\r\n });\r\n return () => controls.stop();\r\n }, [progress, duration, easing, direction, paused]);\r\n\r\n const containerWidth = responsive ? '100%' : (typeof width === 'number' ? width : '100%');\r\n const containerHeight = responsive ? 'auto' : (typeof height === 'number' ? height : (typeof width === 'number' ? width : 'auto'));\r\n\r\n const items = images.map((src, index) => (\r\n \r\n ));\r\n\r\n return (\r\n \r\n \r\n \r\n {showPath && (\r\n \r\n \r\n \r\n )}\r\n\r\n {items.map((item, index) => (\r\n \r\n ))}\r\n \r\n \r\n\r\n {centerContent && (\r\n
\r\n {centerContent}\r\n
\r\n )}\r\n \r\n );\r\n}\r\n" } ], "registryDependencies": [], diff --git a/public/r/OrbitImages-JS-TW.json b/public/r/OrbitImages-JS-TW.json index 868c03376..0edfe9714 100644 --- a/public/r/OrbitImages-JS-TW.json +++ b/public/r/OrbitImages-JS-TW.json @@ -8,7 +8,7 @@ { "type": "registry:component", "path": "OrbitImages/OrbitImages.jsx", - "content": "// Component created by Dominik Koch\n// https://x.com/dominikkoch\n\nimport { useMemo, useEffect, useRef, useState } from 'react';\nimport { motion, useMotionValue, useTransform, animate } from 'motion/react';\n\nfunction generateEllipsePath(cx, cy, rx, ry) {\n return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;\n}\n\nfunction generateCirclePath(cx, cy, r) {\n return generateEllipsePath(cx, cy, r, r);\n}\n\nfunction generateSquarePath(cx, cy, size) {\n const h = size / 2;\n return `M ${cx - h} ${cy - h} L ${cx + h} ${cy - h} L ${cx + h} ${cy + h} L ${cx - h} ${cy + h} Z`;\n}\n\nfunction generateRectanglePath(cx, cy, w, h) {\n const hw = w / 2;\n const hh = h / 2;\n return `M ${cx - hw} ${cy - hh} L ${cx + hw} ${cy - hh} L ${cx + hw} ${cy + hh} L ${cx - hw} ${cy + hh} Z`;\n}\n\nfunction generateTrianglePath(cx, cy, size) {\n const height = (size * Math.sqrt(3)) / 2;\n const hs = size / 2;\n return `M ${cx} ${cy - height / 1.5} L ${cx + hs} ${cy + height / 3} L ${cx - hs} ${cy + height / 3} Z`;\n}\n\nfunction generateStarPath(cx, cy, outerR, innerR, points) {\n const step = Math.PI / points;\n let path = '';\n for (let i = 0; i < 2 * points; i++) {\n const r = i % 2 === 0 ? outerR : innerR;\n const angle = i * step - Math.PI / 2;\n const x = cx + r * Math.cos(angle);\n const y = cy + r * Math.sin(angle);\n path += i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`;\n }\n return path + ' Z';\n}\n\nfunction generateHeartPath(cx, cy, size) {\n const s = size / 30;\n return `M ${cx} ${cy + 12 * s} C ${cx - 20 * s} ${cy - 5 * s}, ${cx - 12 * s} ${cy - 18 * s}, ${cx} ${cy - 8 * s} C ${cx + 12 * s} ${cy - 18 * s}, ${cx + 20 * s} ${cy - 5 * s}, ${cx} ${cy + 12 * s}`;\n}\n\nfunction generateInfinityPath(cx, cy, w, h) {\n const hw = w / 2;\n const hh = h / 2;\n return `M ${cx} ${cy} C ${cx + hw * 0.5} ${cy - hh}, ${cx + hw} ${cy - hh}, ${cx + hw} ${cy} C ${cx + hw} ${cy + hh}, ${cx + hw * 0.5} ${cy + hh}, ${cx} ${cy} C ${cx - hw * 0.5} ${cy + hh}, ${cx - hw} ${cy + hh}, ${cx - hw} ${cy} C ${cx - hw} ${cy - hh}, ${cx - hw * 0.5} ${cy - hh}, ${cx} ${cy}`;\n}\n\nfunction generateWavePath(cx, cy, w, amplitude, waves) {\n const pts = [];\n const segs = waves * 20;\n const hw = w / 2;\n for (let i = 0; i <= segs; i++) {\n const x = cx - hw + (w * i) / segs;\n const y = cy + Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\n pts.push(i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`);\n }\n for (let i = segs; i >= 0; i--) {\n const x = cx - hw + (w * i) / segs;\n const y = cy - Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\n pts.push(`L ${x} ${y}`);\n }\n return pts.join(' ') + ' Z';\n}\n\nfunction OrbitItem({ item, index, totalItems, path, itemSize, rotation, progress, fill }) {\n const itemOffset = fill ? (index / totalItems) * 100 : 0;\n\n const offsetDistance = useTransform(progress, (p) => {\n const offset = (((p + itemOffset) % 100) + 100) % 100;\n return `${offset}%`;\n });\n\n return (\n \n
{item}
\n \n );\n}\n\nexport default function OrbitImages({\n images = [],\n altPrefix = 'Orbiting image',\n shape = 'ellipse',\n customPath,\n baseWidth = 1400,\n radiusX = 700,\n radiusY = 170,\n radius = 300,\n starPoints = 5,\n starInnerRatio = 0.5,\n rotation = -8,\n duration = 40,\n itemSize = 64,\n direction = 'normal',\n fill = true,\n width = 100,\n height = 100,\n className = '',\n showPath = false,\n pathColor = 'rgba(0,0,0,0.1)',\n pathWidth = 2,\n easing = 'linear',\n paused = false,\n centerContent,\n responsive = false,\n}) {\n const containerRef = useRef(null);\n const [scale, setScale] = useState(1);\n\n const designCenterX = baseWidth / 2;\n const designCenterY = baseWidth / 2;\n\n const path = useMemo(() => {\n switch (shape) {\n case 'circle':\n return generateCirclePath(designCenterX, designCenterY, radius);\n case 'ellipse':\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\n case 'square':\n return generateSquarePath(designCenterX, designCenterY, radius * 2);\n case 'rectangle':\n return generateRectanglePath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\n case 'triangle':\n return generateTrianglePath(designCenterX, designCenterY, radius * 2);\n case 'star':\n return generateStarPath(designCenterX, designCenterY, radius, radius * starInnerRatio, starPoints);\n case 'heart':\n return generateHeartPath(designCenterX, designCenterY, radius * 2);\n case 'infinity':\n return generateInfinityPath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\n case 'wave':\n return generateWavePath(designCenterX, designCenterY, radiusX * 2, radiusY, 3);\n case 'custom':\n return customPath || generateCirclePath(designCenterX, designCenterY, radius);\n default:\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\n }\n }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]);\n\n useEffect(() => {\n if (!responsive || !containerRef.current) return;\n const updateScale = () => {\n if (!containerRef.current) return;\n setScale(containerRef.current.clientWidth / baseWidth);\n };\n updateScale();\n const observer = new ResizeObserver(updateScale);\n observer.observe(containerRef.current);\n return () => observer.disconnect();\n }, [responsive, baseWidth]);\n\n const progress = useMotionValue(0);\n\n useEffect(() => {\n if (paused) return;\n const controls = animate(progress, direction === 'reverse' ? -100 : 100, {\n duration,\n ease: easing,\n repeat: Infinity,\n repeatType: 'loop',\n });\n return () => controls.stop();\n }, [progress, duration, easing, direction, paused]);\n\n const containerWidth = responsive ? '100%' : (typeof width === 'number' ? width : '100%');\n const containerHeight = responsive ? 'auto' : (typeof height === 'number' ? height : (typeof width === 'number' ? width : 'auto'));\n\n const items = images.map((src, index) => (\n \n ));\n\n return (\n \n \n \n {showPath && (\n \n \n \n )}\n\n {items.map((item, index) => (\n \n ))}\n \n \n\n {centerContent && (\n
\n {centerContent}\n
\n )}\n \n );\n}\n" + "content": "// Component created by Dominik Koch\r\n// https://x.com/dominikkoch\r\n\r\nimport { useMemo, useEffect, useLayoutEffect, useRef, useState } from 'react';\r\nimport { motion, useMotionValue, useTransform, animate } from 'motion/react';\r\n\r\nfunction generateEllipsePath(cx, cy, rx, ry) {\r\n return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;\r\n}\r\n\r\nfunction generateCirclePath(cx, cy, r) {\r\n return generateEllipsePath(cx, cy, r, r);\r\n}\r\n\r\nfunction generateSquarePath(cx, cy, size) {\r\n const h = size / 2;\r\n return `M ${cx - h} ${cy - h} L ${cx + h} ${cy - h} L ${cx + h} ${cy + h} L ${cx - h} ${cy + h} Z`;\r\n}\r\n\r\nfunction generateRectanglePath(cx, cy, w, h) {\r\n const hw = w / 2;\r\n const hh = h / 2;\r\n return `M ${cx - hw} ${cy - hh} L ${cx + hw} ${cy - hh} L ${cx + hw} ${cy + hh} L ${cx - hw} ${cy + hh} Z`;\r\n}\r\n\r\nfunction generateTrianglePath(cx, cy, size) {\r\n const height = (size * Math.sqrt(3)) / 2;\r\n const hs = size / 2;\r\n return `M ${cx} ${cy - height / 1.5} L ${cx + hs} ${cy + height / 3} L ${cx - hs} ${cy + height / 3} Z`;\r\n}\r\n\r\nfunction generateStarPath(cx, cy, outerR, innerR, points) {\r\n const step = Math.PI / points;\r\n let path = '';\r\n for (let i = 0; i < 2 * points; i++) {\r\n const r = i % 2 === 0 ? outerR : innerR;\r\n const angle = i * step - Math.PI / 2;\r\n const x = cx + r * Math.cos(angle);\r\n const y = cy + r * Math.sin(angle);\r\n path += i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`;\r\n }\r\n return path + ' Z';\r\n}\r\n\r\nfunction generateHeartPath(cx, cy, size) {\r\n const s = size / 30;\r\n return `M ${cx} ${cy + 12 * s} C ${cx - 20 * s} ${cy - 5 * s}, ${cx - 12 * s} ${cy - 18 * s}, ${cx} ${cy - 8 * s} C ${cx + 12 * s} ${cy - 18 * s}, ${cx + 20 * s} ${cy - 5 * s}, ${cx} ${cy + 12 * s}`;\r\n}\r\n\r\nfunction generateInfinityPath(cx, cy, w, h) {\r\n const hw = w / 2;\r\n const hh = h / 2;\r\n return `M ${cx} ${cy} C ${cx + hw * 0.5} ${cy - hh}, ${cx + hw} ${cy - hh}, ${cx + hw} ${cy} C ${cx + hw} ${cy + hh}, ${cx + hw * 0.5} ${cy + hh}, ${cx} ${cy} C ${cx - hw * 0.5} ${cy + hh}, ${cx - hw} ${cy + hh}, ${cx - hw} ${cy} C ${cx - hw} ${cy - hh}, ${cx - hw * 0.5} ${cy - hh}, ${cx} ${cy}`;\r\n}\r\n\r\nfunction generateWavePath(cx, cy, w, amplitude, waves) {\r\n const pts = [];\r\n const segs = waves * 20;\r\n const hw = w / 2;\r\n for (let i = 0; i <= segs; i++) {\r\n const x = cx - hw + (w * i) / segs;\r\n const y = cy + Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\r\n pts.push(i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`);\r\n }\r\n for (let i = segs; i >= 0; i--) {\r\n const x = cx - hw + (w * i) / segs;\r\n const y = cy - Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\r\n pts.push(`L ${x} ${y}`);\r\n }\r\n return pts.join(' ') + ' Z';\r\n}\r\n\r\nfunction OrbitItem({ item, index, totalItems, path, itemSize, rotation, progress, fill }) {\r\n const itemOffset = fill ? (index / totalItems) * 100 : 0;\r\n\r\n const offsetDistance = useTransform(progress, (p) => {\r\n const offset = (((p + itemOffset) % 100) + 100) % 100;\r\n return `${offset}%`;\r\n });\r\n\r\n return (\r\n \r\n
{item}
\r\n \r\n );\r\n}\r\n\r\nexport default function OrbitImages({\r\n images = [],\r\n altPrefix = 'Orbiting image',\r\n shape = 'ellipse',\r\n customPath,\r\n baseWidth = 1400,\r\n radiusX = 700,\r\n radiusY = 170,\r\n radius = 300,\r\n starPoints = 5,\r\n starInnerRatio = 0.5,\r\n rotation = -8,\r\n duration = 40,\r\n itemSize = 64,\r\n direction = 'normal',\r\n fill = true,\r\n width = 100,\r\n height = 100,\r\n className = '',\r\n showPath = false,\r\n pathColor = 'rgba(0,0,0,0.1)',\r\n pathWidth = 2,\r\n easing = 'linear',\r\n paused = false,\r\n centerContent,\r\n responsive = false,\r\n}) {\r\n const containerRef = useRef(null);\r\n const [scale, setScale] = useState(null);\r\n\r\n const designCenterX = baseWidth / 2;\r\n const designCenterY = baseWidth / 2;\r\n\r\n const path = useMemo(() => {\r\n switch (shape) {\r\n case 'circle':\r\n return generateCirclePath(designCenterX, designCenterY, radius);\r\n case 'ellipse':\r\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\r\n case 'square':\r\n return generateSquarePath(designCenterX, designCenterY, radius * 2);\r\n case 'rectangle':\r\n return generateRectanglePath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\r\n case 'triangle':\r\n return generateTrianglePath(designCenterX, designCenterY, radius * 2);\r\n case 'star':\r\n return generateStarPath(designCenterX, designCenterY, radius, radius * starInnerRatio, starPoints);\r\n case 'heart':\r\n return generateHeartPath(designCenterX, designCenterY, radius * 2);\r\n case 'infinity':\r\n return generateInfinityPath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\r\n case 'wave':\r\n return generateWavePath(designCenterX, designCenterY, radiusX * 2, radiusY, 3);\r\n case 'custom':\r\n return customPath || generateCirclePath(designCenterX, designCenterY, radius);\r\n default:\r\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\r\n }\r\n }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]);\r\n\r\n useLayoutEffect(() => {\r\n if (!responsive || !containerRef.current) return;\r\n const updateScale = () => {\r\n if (!containerRef.current) return;\r\n setScale(containerRef.current.clientWidth / baseWidth);\r\n };\r\n updateScale();\r\n const observer = new ResizeObserver(updateScale);\r\n observer.observe(containerRef.current);\r\n return () => observer.disconnect();\r\n }, [responsive, baseWidth]);\r\n\r\n const progress = useMotionValue(0);\r\n\r\n useEffect(() => {\r\n if (paused) return;\r\n const controls = animate(progress, direction === 'reverse' ? -100 : 100, {\r\n duration,\r\n ease: easing,\r\n repeat: Infinity,\r\n repeatType: 'loop',\r\n });\r\n return () => controls.stop();\r\n }, [progress, duration, easing, direction, paused]);\r\n\r\n const containerWidth = responsive ? '100%' : (typeof width === 'number' ? width : '100%');\r\n const containerHeight = responsive ? 'auto' : (typeof height === 'number' ? height : (typeof width === 'number' ? width : 'auto'));\r\n\r\n const items = images.map((src, index) => (\r\n \r\n ));\r\n\r\n return (\r\n \r\n \r\n \r\n {showPath && (\r\n \r\n \r\n \r\n )}\r\n\r\n {items.map((item, index) => (\r\n \r\n ))}\r\n \r\n \r\n\r\n {centerContent && (\r\n
\r\n {centerContent}\r\n
\r\n )}\r\n \r\n );\r\n}\r\n" } ], "registryDependencies": [], diff --git a/public/r/OrbitImages-TS-CSS.json b/public/r/OrbitImages-TS-CSS.json index 7e4c0e41a..75ac9a87b 100644 --- a/public/r/OrbitImages-TS-CSS.json +++ b/public/r/OrbitImages-TS-CSS.json @@ -8,12 +8,12 @@ { "type": "registry:component", "path": "OrbitImages/OrbitImages.css", - "content": ".orbit-container {\n position: relative;\n margin-left: auto;\n margin-right: auto;\n}\n\n.orbit-scaling-container {\n width: 100%;\n height: 100%;\n position: relative;\n}\n\n.orbit-scaling-container--responsive {\n position: absolute;\n left: 50%;\n top: 50%;\n transform-origin: center center;\n}\n\n.orbit-rotation-wrapper {\n width: 100%;\n height: 100%;\n transform-origin: center center;\n position: relative;\n}\n\n.orbit-path-svg {\n position: absolute;\n inset: 0;\n pointer-events: none;\n}\n\n.orbit-item {\n position: absolute;\n will-change: transform;\n user-select: none;\n}\n\n.orbit-center-content {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n z-index: 10;\n}\n\n.orbit-image {\n width: 100%;\n height: 100%;\n object-fit: contain;\n}\n" + "content": ".orbit-container {\r\n position: relative;\r\n margin-left: auto;\r\n margin-right: auto;\r\n}\r\n\r\n.orbit-scaling-container {\r\n width: 100%;\r\n height: 100%;\r\n position: relative;\r\n}\r\n\r\n.orbit-scaling-container--responsive {\r\n position: absolute;\r\n left: 50%;\r\n top: 50%;\r\n transform-origin: center center;\r\n}\r\n\r\n.orbit-rotation-wrapper {\r\n width: 100%;\r\n height: 100%;\r\n transform-origin: center center;\r\n position: relative;\r\n}\r\n\r\n.orbit-path-svg {\r\n position: absolute;\r\n inset: 0;\r\n pointer-events: none;\r\n}\r\n\r\n.orbit-item {\r\n position: absolute;\r\n will-change: transform;\r\n user-select: none;\r\n}\r\n\r\n.orbit-center-content {\r\n position: absolute;\r\n inset: 0;\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n z-index: 10;\r\n}\r\n\r\n.orbit-image {\r\n width: 100%;\r\n height: 100%;\r\n object-fit: contain;\r\n}\r\n" }, { "type": "registry:component", "path": "OrbitImages/OrbitImages.tsx", - "content": "// Component created by Dominik Koch\n// https://x.com/dominikkoch\n\nimport { useMemo, useEffect, useRef, useState, ReactNode } from 'react';\nimport { motion, useMotionValue, useTransform, animate, MotionValue } from 'motion/react';\nimport './OrbitImages.css';\n\ntype OrbitShape =\n | 'ellipse'\n | 'circle'\n | 'square'\n | 'rectangle'\n | 'triangle'\n | 'star'\n | 'heart'\n | 'infinity'\n | 'wave'\n | 'custom';\n\ninterface OrbitImagesProps {\n images?: string[];\n altPrefix?: string;\n shape?: OrbitShape;\n customPath?: string;\n baseWidth?: number;\n radiusX?: number;\n radiusY?: number;\n radius?: number;\n starPoints?: number;\n starInnerRatio?: number;\n rotation?: number;\n duration?: number;\n itemSize?: number;\n direction?: 'normal' | 'reverse';\n fill?: boolean;\n width?: number | '100%';\n height?: number | 'auto';\n className?: string;\n showPath?: boolean;\n pathColor?: string;\n pathWidth?: number;\n easing?: 'linear' | 'easeIn' | 'easeOut' | 'easeInOut';\n paused?: boolean;\n centerContent?: ReactNode;\n responsive?: boolean;\n}\n\ninterface OrbitItemProps {\n item: ReactNode;\n index: number;\n totalItems: number;\n path: string;\n itemSize: number;\n rotation: number;\n progress: MotionValue;\n fill: boolean;\n}\n\nfunction generateEllipsePath(cx: number, cy: number, rx: number, ry: number): string {\n return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;\n}\n\nfunction generateCirclePath(cx: number, cy: number, r: number): string {\n return generateEllipsePath(cx, cy, r, r);\n}\n\nfunction generateSquarePath(cx: number, cy: number, size: number): string {\n const h = size / 2;\n return `M ${cx - h} ${cy - h} L ${cx + h} ${cy - h} L ${cx + h} ${cy + h} L ${cx - h} ${cy + h} Z`;\n}\n\nfunction generateRectanglePath(cx: number, cy: number, w: number, h: number): string {\n const hw = w / 2;\n const hh = h / 2;\n return `M ${cx - hw} ${cy - hh} L ${cx + hw} ${cy - hh} L ${cx + hw} ${cy + hh} L ${cx - hw} ${cy + hh} Z`;\n}\n\nfunction generateTrianglePath(cx: number, cy: number, size: number): string {\n const height = (size * Math.sqrt(3)) / 2;\n const hs = size / 2;\n return `M ${cx} ${cy - height / 1.5} L ${cx + hs} ${cy + height / 3} L ${cx - hs} ${cy + height / 3} Z`;\n}\n\nfunction generateStarPath(cx: number, cy: number, outerR: number, innerR: number, points: number): string {\n const step = Math.PI / points;\n let path = '';\n for (let i = 0; i < 2 * points; i++) {\n const r = i % 2 === 0 ? outerR : innerR;\n const angle = i * step - Math.PI / 2;\n const x = cx + r * Math.cos(angle);\n const y = cy + r * Math.sin(angle);\n path += i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`;\n }\n return path + ' Z';\n}\n\nfunction generateHeartPath(cx: number, cy: number, size: number): string {\n const s = size / 30;\n return `M ${cx} ${cy + 12 * s} C ${cx - 20 * s} ${cy - 5 * s}, ${cx - 12 * s} ${cy - 18 * s}, ${cx} ${cy - 8 * s} C ${cx + 12 * s} ${cy - 18 * s}, ${cx + 20 * s} ${cy - 5 * s}, ${cx} ${cy + 12 * s}`;\n}\n\nfunction generateInfinityPath(cx: number, cy: number, w: number, h: number): string {\n const hw = w / 2;\n const hh = h / 2;\n return `M ${cx} ${cy} C ${cx + hw * 0.5} ${cy - hh}, ${cx + hw} ${cy - hh}, ${cx + hw} ${cy} C ${cx + hw} ${cy + hh}, ${cx + hw * 0.5} ${cy + hh}, ${cx} ${cy} C ${cx - hw * 0.5} ${cy + hh}, ${cx - hw} ${cy + hh}, ${cx - hw} ${cy} C ${cx - hw} ${cy - hh}, ${cx - hw * 0.5} ${cy - hh}, ${cx} ${cy}`;\n}\n\nfunction generateWavePath(cx: number, cy: number, w: number, amplitude: number, waves: number): string {\n const pts: string[] = [];\n const segs = waves * 20;\n const hw = w / 2;\n for (let i = 0; i <= segs; i++) {\n const x = cx - hw + (w * i) / segs;\n const y = cy + Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\n pts.push(i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`);\n }\n for (let i = segs; i >= 0; i--) {\n const x = cx - hw + (w * i) / segs;\n const y = cy - Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\n pts.push(`L ${x} ${y}`);\n }\n return pts.join(' ') + ' Z';\n}\n\nfunction OrbitItem({ item, index, totalItems, path, itemSize, rotation, progress, fill }: OrbitItemProps) {\n const itemOffset = fill ? (index / totalItems) * 100 : 0;\n\n const offsetDistance = useTransform(progress, (p: number) => {\n const offset = (((p + itemOffset) % 100) + 100) % 100;\n return `${offset}%`;\n });\n\n return (\n \n
{item}
\n \n );\n}\n\nexport default function OrbitImages({\n images = [],\n altPrefix = 'Orbiting image',\n shape = 'ellipse',\n customPath,\n baseWidth = 1400,\n radiusX = 700,\n radiusY = 170,\n radius = 300,\n starPoints = 5,\n starInnerRatio = 0.5,\n rotation = -8,\n duration = 40,\n itemSize = 64,\n direction = 'normal',\n fill = true,\n width = 100,\n height = 100,\n className = '',\n showPath = false,\n pathColor = 'rgba(0,0,0,0.1)',\n pathWidth = 2,\n easing = 'linear',\n paused = false,\n centerContent,\n responsive = false,\n}: OrbitImagesProps) {\n const containerRef = useRef(null);\n const [scale, setScale] = useState(1);\n\n const designCenterX = baseWidth / 2;\n const designCenterY = baseWidth / 2;\n\n const path = useMemo(() => {\n switch (shape) {\n case 'circle':\n return generateCirclePath(designCenterX, designCenterY, radius);\n case 'ellipse':\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\n case 'square':\n return generateSquarePath(designCenterX, designCenterY, radius * 2);\n case 'rectangle':\n return generateRectanglePath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\n case 'triangle':\n return generateTrianglePath(designCenterX, designCenterY, radius * 2);\n case 'star':\n return generateStarPath(designCenterX, designCenterY, radius, radius * starInnerRatio, starPoints);\n case 'heart':\n return generateHeartPath(designCenterX, designCenterY, radius * 2);\n case 'infinity':\n return generateInfinityPath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\n case 'wave':\n return generateWavePath(designCenterX, designCenterY, radiusX * 2, radiusY, 3);\n case 'custom':\n return customPath || generateCirclePath(designCenterX, designCenterY, radius);\n default:\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\n }\n }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]);\n\n useEffect(() => {\n if (!responsive || !containerRef.current) return;\n const updateScale = () => {\n if (!containerRef.current) return;\n setScale(containerRef.current.clientWidth / baseWidth);\n };\n updateScale();\n const observer = new ResizeObserver(updateScale);\n observer.observe(containerRef.current);\n return () => observer.disconnect();\n }, [responsive, baseWidth]);\n\n const progress = useMotionValue(0);\n\n useEffect(() => {\n if (paused) return;\n const controls = animate(progress, direction === 'reverse' ? -100 : 100, {\n duration,\n ease: easing,\n repeat: Infinity,\n repeatType: 'loop',\n });\n return () => controls.stop();\n }, [progress, duration, easing, direction, paused]);\n\n const containerWidth = responsive ? '100%' : (typeof width === 'number' ? width : '100%');\n const containerHeight = responsive ? 'auto' : (typeof height === 'number' ? height : (typeof width === 'number' ? width : 'auto'));\n\n const items = images.map((src, index) => (\n \n ));\n\n return (\n \n \n \n {showPath && (\n \n \n \n )}\n\n {items.map((item, index) => (\n \n ))}\n \n \n\n {centerContent && (\n
\n {centerContent}\n
\n )}\n \n );\n}\n" + "content": "// Component created by Dominik Koch\r\n// https://x.com/dominikkoch\r\n\r\nimport { useMemo, useEffect, useLayoutEffect, useRef, useState, ReactNode } from 'react';\r\nimport { motion, useMotionValue, useTransform, animate, MotionValue } from 'motion/react';\r\nimport './OrbitImages.css';\r\n\r\ntype OrbitShape =\r\n | 'ellipse'\r\n | 'circle'\r\n | 'square'\r\n | 'rectangle'\r\n | 'triangle'\r\n | 'star'\r\n | 'heart'\r\n | 'infinity'\r\n | 'wave'\r\n | 'custom';\r\n\r\ninterface OrbitImagesProps {\r\n images?: string[];\r\n altPrefix?: string;\r\n shape?: OrbitShape;\r\n customPath?: string;\r\n baseWidth?: number;\r\n radiusX?: number;\r\n radiusY?: number;\r\n radius?: number;\r\n starPoints?: number;\r\n starInnerRatio?: number;\r\n rotation?: number;\r\n duration?: number;\r\n itemSize?: number;\r\n direction?: 'normal' | 'reverse';\r\n fill?: boolean;\r\n width?: number | '100%';\r\n height?: number | 'auto';\r\n className?: string;\r\n showPath?: boolean;\r\n pathColor?: string;\r\n pathWidth?: number;\r\n easing?: 'linear' | 'easeIn' | 'easeOut' | 'easeInOut';\r\n paused?: boolean;\r\n centerContent?: ReactNode;\r\n responsive?: boolean;\r\n}\r\n\r\ninterface OrbitItemProps {\r\n item: ReactNode;\r\n index: number;\r\n totalItems: number;\r\n path: string;\r\n itemSize: number;\r\n rotation: number;\r\n progress: MotionValue;\r\n fill: boolean;\r\n}\r\n\r\nfunction generateEllipsePath(cx: number, cy: number, rx: number, ry: number): string {\r\n return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;\r\n}\r\n\r\nfunction generateCirclePath(cx: number, cy: number, r: number): string {\r\n return generateEllipsePath(cx, cy, r, r);\r\n}\r\n\r\nfunction generateSquarePath(cx: number, cy: number, size: number): string {\r\n const h = size / 2;\r\n return `M ${cx - h} ${cy - h} L ${cx + h} ${cy - h} L ${cx + h} ${cy + h} L ${cx - h} ${cy + h} Z`;\r\n}\r\n\r\nfunction generateRectanglePath(cx: number, cy: number, w: number, h: number): string {\r\n const hw = w / 2;\r\n const hh = h / 2;\r\n return `M ${cx - hw} ${cy - hh} L ${cx + hw} ${cy - hh} L ${cx + hw} ${cy + hh} L ${cx - hw} ${cy + hh} Z`;\r\n}\r\n\r\nfunction generateTrianglePath(cx: number, cy: number, size: number): string {\r\n const height = (size * Math.sqrt(3)) / 2;\r\n const hs = size / 2;\r\n return `M ${cx} ${cy - height / 1.5} L ${cx + hs} ${cy + height / 3} L ${cx - hs} ${cy + height / 3} Z`;\r\n}\r\n\r\nfunction generateStarPath(cx: number, cy: number, outerR: number, innerR: number, points: number): string {\r\n const step = Math.PI / points;\r\n let path = '';\r\n for (let i = 0; i < 2 * points; i++) {\r\n const r = i % 2 === 0 ? outerR : innerR;\r\n const angle = i * step - Math.PI / 2;\r\n const x = cx + r * Math.cos(angle);\r\n const y = cy + r * Math.sin(angle);\r\n path += i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`;\r\n }\r\n return path + ' Z';\r\n}\r\n\r\nfunction generateHeartPath(cx: number, cy: number, size: number): string {\r\n const s = size / 30;\r\n return `M ${cx} ${cy + 12 * s} C ${cx - 20 * s} ${cy - 5 * s}, ${cx - 12 * s} ${cy - 18 * s}, ${cx} ${cy - 8 * s} C ${cx + 12 * s} ${cy - 18 * s}, ${cx + 20 * s} ${cy - 5 * s}, ${cx} ${cy + 12 * s}`;\r\n}\r\n\r\nfunction generateInfinityPath(cx: number, cy: number, w: number, h: number): string {\r\n const hw = w / 2;\r\n const hh = h / 2;\r\n return `M ${cx} ${cy} C ${cx + hw * 0.5} ${cy - hh}, ${cx + hw} ${cy - hh}, ${cx + hw} ${cy} C ${cx + hw} ${cy + hh}, ${cx + hw * 0.5} ${cy + hh}, ${cx} ${cy} C ${cx - hw * 0.5} ${cy + hh}, ${cx - hw} ${cy + hh}, ${cx - hw} ${cy} C ${cx - hw} ${cy - hh}, ${cx - hw * 0.5} ${cy - hh}, ${cx} ${cy}`;\r\n}\r\n\r\nfunction generateWavePath(cx: number, cy: number, w: number, amplitude: number, waves: number): string {\r\n const pts: string[] = [];\r\n const segs = waves * 20;\r\n const hw = w / 2;\r\n for (let i = 0; i <= segs; i++) {\r\n const x = cx - hw + (w * i) / segs;\r\n const y = cy + Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\r\n pts.push(i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`);\r\n }\r\n for (let i = segs; i >= 0; i--) {\r\n const x = cx - hw + (w * i) / segs;\r\n const y = cy - Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\r\n pts.push(`L ${x} ${y}`);\r\n }\r\n return pts.join(' ') + ' Z';\r\n}\r\n\r\nfunction OrbitItem({ item, index, totalItems, path, itemSize, rotation, progress, fill }: OrbitItemProps) {\r\n const itemOffset = fill ? (index / totalItems) * 100 : 0;\r\n\r\n const offsetDistance = useTransform(progress, (p: number) => {\r\n const offset = (((p + itemOffset) % 100) + 100) % 100;\r\n return `${offset}%`;\r\n });\r\n\r\n return (\r\n \r\n
{item}
\r\n \r\n );\r\n}\r\n\r\nexport default function OrbitImages({\r\n images = [],\r\n altPrefix = 'Orbiting image',\r\n shape = 'ellipse',\r\n customPath,\r\n baseWidth = 1400,\r\n radiusX = 700,\r\n radiusY = 170,\r\n radius = 300,\r\n starPoints = 5,\r\n starInnerRatio = 0.5,\r\n rotation = -8,\r\n duration = 40,\r\n itemSize = 64,\r\n direction = 'normal',\r\n fill = true,\r\n width = 100,\r\n height = 100,\r\n className = '',\r\n showPath = false,\r\n pathColor = 'rgba(0,0,0,0.1)',\r\n pathWidth = 2,\r\n easing = 'linear',\r\n paused = false,\r\n centerContent,\r\n responsive = false,\r\n}: OrbitImagesProps) {\r\n const containerRef = useRef(null);\r\n const [scale, setScale] = useState(null);\r\n\r\n const designCenterX = baseWidth / 2;\r\n const designCenterY = baseWidth / 2;\r\n\r\n const path = useMemo(() => {\r\n switch (shape) {\r\n case 'circle':\r\n return generateCirclePath(designCenterX, designCenterY, radius);\r\n case 'ellipse':\r\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\r\n case 'square':\r\n return generateSquarePath(designCenterX, designCenterY, radius * 2);\r\n case 'rectangle':\r\n return generateRectanglePath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\r\n case 'triangle':\r\n return generateTrianglePath(designCenterX, designCenterY, radius * 2);\r\n case 'star':\r\n return generateStarPath(designCenterX, designCenterY, radius, radius * starInnerRatio, starPoints);\r\n case 'heart':\r\n return generateHeartPath(designCenterX, designCenterY, radius * 2);\r\n case 'infinity':\r\n return generateInfinityPath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\r\n case 'wave':\r\n return generateWavePath(designCenterX, designCenterY, radiusX * 2, radiusY, 3);\r\n case 'custom':\r\n return customPath || generateCirclePath(designCenterX, designCenterY, radius);\r\n default:\r\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\r\n }\r\n }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]);\r\n\r\n useLayoutEffect(() => {\r\n if (!responsive || !containerRef.current) return;\r\n const updateScale = () => {\r\n if (!containerRef.current) return;\r\n setScale(containerRef.current.clientWidth / baseWidth);\r\n };\r\n updateScale();\r\n const observer = new ResizeObserver(updateScale);\r\n observer.observe(containerRef.current);\r\n return () => observer.disconnect();\r\n }, [responsive, baseWidth]);\r\n\r\n const progress = useMotionValue(0);\r\n\r\n useEffect(() => {\r\n if (paused) return;\r\n const controls = animate(progress, direction === 'reverse' ? -100 : 100, {\r\n duration,\r\n ease: easing,\r\n repeat: Infinity,\r\n repeatType: 'loop',\r\n });\r\n return () => controls.stop();\r\n }, [progress, duration, easing, direction, paused]);\r\n\r\n const containerWidth = responsive ? '100%' : (typeof width === 'number' ? width : '100%');\r\n const containerHeight = responsive ? 'auto' : (typeof height === 'number' ? height : (typeof width === 'number' ? width : 'auto'));\r\n\r\n const items = images.map((src, index) => (\r\n \r\n ));\r\n\r\n return (\r\n \r\n \r\n \r\n {showPath && (\r\n \r\n \r\n \r\n )}\r\n\r\n {items.map((item, index) => (\r\n \r\n ))}\r\n \r\n \r\n\r\n {centerContent && (\r\n
\r\n {centerContent}\r\n
\r\n )}\r\n \r\n );\r\n}\r\n" } ], "registryDependencies": [], diff --git a/public/r/OrbitImages-TS-TW.json b/public/r/OrbitImages-TS-TW.json index 741b9808f..9a091ac17 100644 --- a/public/r/OrbitImages-TS-TW.json +++ b/public/r/OrbitImages-TS-TW.json @@ -8,7 +8,7 @@ { "type": "registry:component", "path": "OrbitImages/OrbitImages.tsx", - "content": "// Component created by Dominik Koch\n// https://x.com/dominikkoch\n\nimport { useMemo, useEffect, useRef, useState, ReactNode } from 'react';\nimport { motion, useMotionValue, useTransform, animate, MotionValue } from 'motion/react';\n\ntype OrbitShape =\n | 'ellipse'\n | 'circle'\n | 'square'\n | 'rectangle'\n | 'triangle'\n | 'star'\n | 'heart'\n | 'infinity'\n | 'wave'\n | 'custom';\n\ninterface OrbitImagesProps {\n images?: string[];\n altPrefix?: string;\n shape?: OrbitShape;\n customPath?: string;\n baseWidth?: number;\n radiusX?: number;\n radiusY?: number;\n radius?: number;\n starPoints?: number;\n starInnerRatio?: number;\n rotation?: number;\n duration?: number;\n itemSize?: number;\n direction?: 'normal' | 'reverse';\n fill?: boolean;\n width?: number | '100%';\n height?: number | 'auto';\n className?: string;\n showPath?: boolean;\n pathColor?: string;\n pathWidth?: number;\n easing?: 'linear' | 'easeIn' | 'easeOut' | 'easeInOut';\n paused?: boolean;\n centerContent?: ReactNode;\n responsive?: boolean;\n}\n\ninterface OrbitItemProps {\n item: ReactNode;\n index: number;\n totalItems: number;\n path: string;\n itemSize: number;\n rotation: number;\n progress: MotionValue;\n fill: boolean;\n}\n\nfunction generateEllipsePath(cx: number, cy: number, rx: number, ry: number): string {\n return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;\n}\n\nfunction generateCirclePath(cx: number, cy: number, r: number): string {\n return generateEllipsePath(cx, cy, r, r);\n}\n\nfunction generateSquarePath(cx: number, cy: number, size: number): string {\n const h = size / 2;\n return `M ${cx - h} ${cy - h} L ${cx + h} ${cy - h} L ${cx + h} ${cy + h} L ${cx - h} ${cy + h} Z`;\n}\n\nfunction generateRectanglePath(cx: number, cy: number, w: number, h: number): string {\n const hw = w / 2;\n const hh = h / 2;\n return `M ${cx - hw} ${cy - hh} L ${cx + hw} ${cy - hh} L ${cx + hw} ${cy + hh} L ${cx - hw} ${cy + hh} Z`;\n}\n\nfunction generateTrianglePath(cx: number, cy: number, size: number): string {\n const height = (size * Math.sqrt(3)) / 2;\n const hs = size / 2;\n return `M ${cx} ${cy - height / 1.5} L ${cx + hs} ${cy + height / 3} L ${cx - hs} ${cy + height / 3} Z`;\n}\n\nfunction generateStarPath(cx: number, cy: number, outerR: number, innerR: number, points: number): string {\n const step = Math.PI / points;\n let path = '';\n for (let i = 0; i < 2 * points; i++) {\n const r = i % 2 === 0 ? outerR : innerR;\n const angle = i * step - Math.PI / 2;\n const x = cx + r * Math.cos(angle);\n const y = cy + r * Math.sin(angle);\n path += i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`;\n }\n return path + ' Z';\n}\n\nfunction generateHeartPath(cx: number, cy: number, size: number): string {\n const s = size / 30;\n return `M ${cx} ${cy + 12 * s} C ${cx - 20 * s} ${cy - 5 * s}, ${cx - 12 * s} ${cy - 18 * s}, ${cx} ${cy - 8 * s} C ${cx + 12 * s} ${cy - 18 * s}, ${cx + 20 * s} ${cy - 5 * s}, ${cx} ${cy + 12 * s}`;\n}\n\nfunction generateInfinityPath(cx: number, cy: number, w: number, h: number): string {\n const hw = w / 2;\n const hh = h / 2;\n return `M ${cx} ${cy} C ${cx + hw * 0.5} ${cy - hh}, ${cx + hw} ${cy - hh}, ${cx + hw} ${cy} C ${cx + hw} ${cy + hh}, ${cx + hw * 0.5} ${cy + hh}, ${cx} ${cy} C ${cx - hw * 0.5} ${cy + hh}, ${cx - hw} ${cy + hh}, ${cx - hw} ${cy} C ${cx - hw} ${cy - hh}, ${cx - hw * 0.5} ${cy - hh}, ${cx} ${cy}`;\n}\n\nfunction generateWavePath(cx: number, cy: number, w: number, amplitude: number, waves: number): string {\n const pts: string[] = [];\n const segs = waves * 20;\n const hw = w / 2;\n for (let i = 0; i <= segs; i++) {\n const x = cx - hw + (w * i) / segs;\n const y = cy + Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\n pts.push(i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`);\n }\n for (let i = segs; i >= 0; i--) {\n const x = cx - hw + (w * i) / segs;\n const y = cy - Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\n pts.push(`L ${x} ${y}`);\n }\n return pts.join(' ') + ' Z';\n}\n\nfunction OrbitItem({ item, index, totalItems, path, itemSize, rotation, progress, fill }: OrbitItemProps) {\n const itemOffset = fill ? (index / totalItems) * 100 : 0;\n\n const offsetDistance = useTransform(progress, (p: number) => {\n const offset = (((p + itemOffset) % 100) + 100) % 100;\n return `${offset}%`;\n });\n\n return (\n \n
{item}
\n \n );\n}\n\nexport default function OrbitImages({\n images = [],\n altPrefix = 'Orbiting image',\n shape = 'ellipse',\n customPath,\n baseWidth = 1400,\n radiusX = 700,\n radiusY = 170,\n radius = 300,\n starPoints = 5,\n starInnerRatio = 0.5,\n rotation = -8,\n duration = 40,\n itemSize = 64,\n direction = 'normal',\n fill = true,\n width = 100,\n height = 100,\n className = '',\n showPath = false,\n pathColor = 'rgba(0,0,0,0.1)',\n pathWidth = 2,\n easing = 'linear',\n paused = false,\n centerContent,\n responsive = false,\n}: OrbitImagesProps) {\n const containerRef = useRef(null);\n const [scale, setScale] = useState(1);\n\n const designCenterX = baseWidth / 2;\n const designCenterY = baseWidth / 2;\n\n const path = useMemo(() => {\n switch (shape) {\n case 'circle':\n return generateCirclePath(designCenterX, designCenterY, radius);\n case 'ellipse':\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\n case 'square':\n return generateSquarePath(designCenterX, designCenterY, radius * 2);\n case 'rectangle':\n return generateRectanglePath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\n case 'triangle':\n return generateTrianglePath(designCenterX, designCenterY, radius * 2);\n case 'star':\n return generateStarPath(designCenterX, designCenterY, radius, radius * starInnerRatio, starPoints);\n case 'heart':\n return generateHeartPath(designCenterX, designCenterY, radius * 2);\n case 'infinity':\n return generateInfinityPath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\n case 'wave':\n return generateWavePath(designCenterX, designCenterY, radiusX * 2, radiusY, 3);\n case 'custom':\n return customPath || generateCirclePath(designCenterX, designCenterY, radius);\n default:\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\n }\n }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]);\n\n useEffect(() => {\n if (!responsive || !containerRef.current) return;\n const updateScale = () => {\n if (!containerRef.current) return;\n setScale(containerRef.current.clientWidth / baseWidth);\n };\n updateScale();\n const observer = new ResizeObserver(updateScale);\n observer.observe(containerRef.current);\n return () => observer.disconnect();\n }, [responsive, baseWidth]);\n\n const progress = useMotionValue(0);\n\n useEffect(() => {\n if (paused) return;\n const controls = animate(progress, direction === 'reverse' ? -100 : 100, {\n duration,\n ease: easing,\n repeat: Infinity,\n repeatType: 'loop',\n });\n return () => controls.stop();\n }, [progress, duration, easing, direction, paused]);\n\n const containerWidth = responsive ? '100%' : (typeof width === 'number' ? width : '100%');\n const containerHeight = responsive ? 'auto' : (typeof height === 'number' ? height : (typeof width === 'number' ? width : 'auto'));\n\n const items = images.map((src, index) => (\n \n ));\n\n return (\n \n \n \n {showPath && (\n \n \n \n )}\n\n {items.map((item, index) => (\n \n ))}\n \n \n\n {centerContent && (\n
\n {centerContent}\n
\n )}\n \n );\n}\n" + "content": "// Component created by Dominik Koch\r\n// https://x.com/dominikkoch\r\n\r\nimport { useMemo, useEffect, useLayoutEffect, useRef, useState, ReactNode } from 'react';\r\nimport { motion, useMotionValue, useTransform, animate, MotionValue } from 'motion/react';\r\n\r\ntype OrbitShape =\r\n | 'ellipse'\r\n | 'circle'\r\n | 'square'\r\n | 'rectangle'\r\n | 'triangle'\r\n | 'star'\r\n | 'heart'\r\n | 'infinity'\r\n | 'wave'\r\n | 'custom';\r\n\r\ninterface OrbitImagesProps {\r\n images?: string[];\r\n altPrefix?: string;\r\n shape?: OrbitShape;\r\n customPath?: string;\r\n baseWidth?: number;\r\n radiusX?: number;\r\n radiusY?: number;\r\n radius?: number;\r\n starPoints?: number;\r\n starInnerRatio?: number;\r\n rotation?: number;\r\n duration?: number;\r\n itemSize?: number;\r\n direction?: 'normal' | 'reverse';\r\n fill?: boolean;\r\n width?: number | '100%';\r\n height?: number | 'auto';\r\n className?: string;\r\n showPath?: boolean;\r\n pathColor?: string;\r\n pathWidth?: number;\r\n easing?: 'linear' | 'easeIn' | 'easeOut' | 'easeInOut';\r\n paused?: boolean;\r\n centerContent?: ReactNode;\r\n responsive?: boolean;\r\n}\r\n\r\ninterface OrbitItemProps {\r\n item: ReactNode;\r\n index: number;\r\n totalItems: number;\r\n path: string;\r\n itemSize: number;\r\n rotation: number;\r\n progress: MotionValue;\r\n fill: boolean;\r\n}\r\n\r\nfunction generateEllipsePath(cx: number, cy: number, rx: number, ry: number): string {\r\n return `M ${cx - rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx + rx} ${cy} A ${rx} ${ry} 0 1 0 ${cx - rx} ${cy}`;\r\n}\r\n\r\nfunction generateCirclePath(cx: number, cy: number, r: number): string {\r\n return generateEllipsePath(cx, cy, r, r);\r\n}\r\n\r\nfunction generateSquarePath(cx: number, cy: number, size: number): string {\r\n const h = size / 2;\r\n return `M ${cx - h} ${cy - h} L ${cx + h} ${cy - h} L ${cx + h} ${cy + h} L ${cx - h} ${cy + h} Z`;\r\n}\r\n\r\nfunction generateRectanglePath(cx: number, cy: number, w: number, h: number): string {\r\n const hw = w / 2;\r\n const hh = h / 2;\r\n return `M ${cx - hw} ${cy - hh} L ${cx + hw} ${cy - hh} L ${cx + hw} ${cy + hh} L ${cx - hw} ${cy + hh} Z`;\r\n}\r\n\r\nfunction generateTrianglePath(cx: number, cy: number, size: number): string {\r\n const height = (size * Math.sqrt(3)) / 2;\r\n const hs = size / 2;\r\n return `M ${cx} ${cy - height / 1.5} L ${cx + hs} ${cy + height / 3} L ${cx - hs} ${cy + height / 3} Z`;\r\n}\r\n\r\nfunction generateStarPath(cx: number, cy: number, outerR: number, innerR: number, points: number): string {\r\n const step = Math.PI / points;\r\n let path = '';\r\n for (let i = 0; i < 2 * points; i++) {\r\n const r = i % 2 === 0 ? outerR : innerR;\r\n const angle = i * step - Math.PI / 2;\r\n const x = cx + r * Math.cos(angle);\r\n const y = cy + r * Math.sin(angle);\r\n path += i === 0 ? `M ${x} ${y}` : ` L ${x} ${y}`;\r\n }\r\n return path + ' Z';\r\n}\r\n\r\nfunction generateHeartPath(cx: number, cy: number, size: number): string {\r\n const s = size / 30;\r\n return `M ${cx} ${cy + 12 * s} C ${cx - 20 * s} ${cy - 5 * s}, ${cx - 12 * s} ${cy - 18 * s}, ${cx} ${cy - 8 * s} C ${cx + 12 * s} ${cy - 18 * s}, ${cx + 20 * s} ${cy - 5 * s}, ${cx} ${cy + 12 * s}`;\r\n}\r\n\r\nfunction generateInfinityPath(cx: number, cy: number, w: number, h: number): string {\r\n const hw = w / 2;\r\n const hh = h / 2;\r\n return `M ${cx} ${cy} C ${cx + hw * 0.5} ${cy - hh}, ${cx + hw} ${cy - hh}, ${cx + hw} ${cy} C ${cx + hw} ${cy + hh}, ${cx + hw * 0.5} ${cy + hh}, ${cx} ${cy} C ${cx - hw * 0.5} ${cy + hh}, ${cx - hw} ${cy + hh}, ${cx - hw} ${cy} C ${cx - hw} ${cy - hh}, ${cx - hw * 0.5} ${cy - hh}, ${cx} ${cy}`;\r\n}\r\n\r\nfunction generateWavePath(cx: number, cy: number, w: number, amplitude: number, waves: number): string {\r\n const pts: string[] = [];\r\n const segs = waves * 20;\r\n const hw = w / 2;\r\n for (let i = 0; i <= segs; i++) {\r\n const x = cx - hw + (w * i) / segs;\r\n const y = cy + Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\r\n pts.push(i === 0 ? `M ${x} ${y}` : `L ${x} ${y}`);\r\n }\r\n for (let i = segs; i >= 0; i--) {\r\n const x = cx - hw + (w * i) / segs;\r\n const y = cy - Math.sin((i / segs) * waves * 2 * Math.PI) * amplitude;\r\n pts.push(`L ${x} ${y}`);\r\n }\r\n return pts.join(' ') + ' Z';\r\n}\r\n\r\nfunction OrbitItem({ item, index, totalItems, path, itemSize, rotation, progress, fill }: OrbitItemProps) {\r\n const itemOffset = fill ? (index / totalItems) * 100 : 0;\r\n\r\n const offsetDistance = useTransform(progress, (p: number) => {\r\n const offset = (((p + itemOffset) % 100) + 100) % 100;\r\n return `${offset}%`;\r\n });\r\n\r\n return (\r\n \r\n
{item}
\r\n \r\n );\r\n}\r\n\r\nexport default function OrbitImages({\r\n images = [],\r\n altPrefix = 'Orbiting image',\r\n shape = 'ellipse',\r\n customPath,\r\n baseWidth = 1400,\r\n radiusX = 700,\r\n radiusY = 170,\r\n radius = 300,\r\n starPoints = 5,\r\n starInnerRatio = 0.5,\r\n rotation = -8,\r\n duration = 40,\r\n itemSize = 64,\r\n direction = 'normal',\r\n fill = true,\r\n width = 100,\r\n height = 100,\r\n className = '',\r\n showPath = false,\r\n pathColor = 'rgba(0,0,0,0.1)',\r\n pathWidth = 2,\r\n easing = 'linear',\r\n paused = false,\r\n centerContent,\r\n responsive = false,\r\n}: OrbitImagesProps) {\r\n const containerRef = useRef(null);\r\n const [scale, setScale] = useState(null);\r\n\r\n const designCenterX = baseWidth / 2;\r\n const designCenterY = baseWidth / 2;\r\n\r\n const path = useMemo(() => {\r\n switch (shape) {\r\n case 'circle':\r\n return generateCirclePath(designCenterX, designCenterY, radius);\r\n case 'ellipse':\r\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\r\n case 'square':\r\n return generateSquarePath(designCenterX, designCenterY, radius * 2);\r\n case 'rectangle':\r\n return generateRectanglePath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\r\n case 'triangle':\r\n return generateTrianglePath(designCenterX, designCenterY, radius * 2);\r\n case 'star':\r\n return generateStarPath(designCenterX, designCenterY, radius, radius * starInnerRatio, starPoints);\r\n case 'heart':\r\n return generateHeartPath(designCenterX, designCenterY, radius * 2);\r\n case 'infinity':\r\n return generateInfinityPath(designCenterX, designCenterY, radiusX * 2, radiusY * 2);\r\n case 'wave':\r\n return generateWavePath(designCenterX, designCenterY, radiusX * 2, radiusY, 3);\r\n case 'custom':\r\n return customPath || generateCirclePath(designCenterX, designCenterY, radius);\r\n default:\r\n return generateEllipsePath(designCenterX, designCenterY, radiusX, radiusY);\r\n }\r\n }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]);\r\n\r\n useLayoutEffect(() => {\r\n if (!responsive || !containerRef.current) return;\r\n const updateScale = () => {\r\n if (!containerRef.current) return;\r\n setScale(containerRef.current.clientWidth / baseWidth);\r\n };\r\n updateScale();\r\n const observer = new ResizeObserver(updateScale);\r\n observer.observe(containerRef.current);\r\n return () => observer.disconnect();\r\n }, [responsive, baseWidth]);\r\n\r\n const progress = useMotionValue(0);\r\n\r\n useEffect(() => {\r\n if (paused) return;\r\n const controls = animate(progress, direction === 'reverse' ? -100 : 100, {\r\n duration,\r\n ease: easing,\r\n repeat: Infinity,\r\n repeatType: 'loop',\r\n });\r\n return () => controls.stop();\r\n }, [progress, duration, easing, direction, paused]);\r\n\r\n const containerWidth = responsive ? '100%' : (typeof width === 'number' ? width : '100%');\r\n const containerHeight = responsive ? 'auto' : (typeof height === 'number' ? height : (typeof width === 'number' ? width : 'auto'));\r\n\r\n const items = images.map((src, index) => (\r\n \r\n ));\r\n\r\n return (\r\n \r\n \r\n \r\n {showPath && (\r\n \r\n \r\n \r\n )}\r\n\r\n {items.map((item, index) => (\r\n \r\n ))}\r\n \r\n \r\n\r\n {centerContent && (\r\n
\r\n {centerContent}\r\n
\r\n )}\r\n \r\n );\r\n}\r\n" } ], "registryDependencies": [], diff --git a/src/content/Animations/OrbitImages/OrbitImages.jsx b/src/content/Animations/OrbitImages/OrbitImages.jsx index 402c92719..dce143ac8 100644 --- a/src/content/Animations/OrbitImages/OrbitImages.jsx +++ b/src/content/Animations/OrbitImages/OrbitImages.jsx @@ -1,7 +1,7 @@ // Component created by Dominik Koch // https://x.com/dominikkoch -import { useMemo, useEffect, useRef, useState } from 'react'; +import { useMemo, useEffect, useLayoutEffect, useRef, useState } from 'react'; import { motion, useMotionValue, useTransform, animate } from 'motion/react'; import './OrbitImages.css'; @@ -124,7 +124,7 @@ export default function OrbitImages({ responsive = false, }) { const containerRef = useRef(null); - const [scale, setScale] = useState(1); + const [scale, setScale] = useState(null); const designCenterX = baseWidth / 2; const designCenterY = baseWidth / 2; @@ -156,7 +156,7 @@ export default function OrbitImages({ } }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]); - useEffect(() => { + useLayoutEffect(() => { if (!responsive || !containerRef.current) return; const updateScale = () => { if (!containerRef.current) return; @@ -210,7 +210,8 @@ export default function OrbitImages({ style={{ width: responsive ? baseWidth : '100%', height: responsive ? baseWidth : '100%', - transform: responsive ? `translate(-50%, -50%) scale(${scale})` : undefined, + transform: responsive && scale !== null ? `translate(-50%, -50%) scale(${scale})` : undefined, + visibility: responsive && scale === null ? 'hidden' : undefined, }} >
- + )} diff --git a/src/tailwind/Animations/OrbitImages/OrbitImages.jsx b/src/tailwind/Animations/OrbitImages/OrbitImages.jsx index 266a1982c..3682df456 100644 --- a/src/tailwind/Animations/OrbitImages/OrbitImages.jsx +++ b/src/tailwind/Animations/OrbitImages/OrbitImages.jsx @@ -1,7 +1,7 @@ // Component created by Dominik Koch // https://x.com/dominikkoch -import { useMemo, useEffect, useRef, useState } from 'react'; +import { useMemo, useEffect, useLayoutEffect, useRef, useState } from 'react'; import { motion, useMotionValue, useTransform, animate } from 'motion/react'; function generateEllipsePath(cx, cy, rx, ry) { @@ -123,7 +123,7 @@ export default function OrbitImages({ responsive = false, }) { const containerRef = useRef(null); - const [scale, setScale] = useState(1); + const [scale, setScale] = useState(null); const designCenterX = baseWidth / 2; const designCenterY = baseWidth / 2; @@ -155,7 +155,7 @@ export default function OrbitImages({ } }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]); - useEffect(() => { + useLayoutEffect(() => { if (!responsive || !containerRef.current) return; const updateScale = () => { if (!containerRef.current) return; @@ -209,7 +209,8 @@ export default function OrbitImages({ style={{ width: responsive ? baseWidth : '100%', height: responsive ? baseWidth : '100%', - transform: responsive ? `translate(-50%, -50%) scale(${scale})` : undefined, + transform: responsive && scale !== null ? `translate(-50%, -50%) scale(${scale})` : undefined, + visibility: responsive && scale === null ? 'hidden' : undefined, transformOrigin: 'center center', }} > @@ -227,7 +228,7 @@ export default function OrbitImages({ viewBox={`0 0 ${baseWidth} ${baseWidth}`} className="absolute inset-0 pointer-events-none" > - + )} diff --git a/src/ts-default/Animations/OrbitImages/OrbitImages.tsx b/src/ts-default/Animations/OrbitImages/OrbitImages.tsx index 95a1e879c..698fd33a4 100644 --- a/src/ts-default/Animations/OrbitImages/OrbitImages.tsx +++ b/src/ts-default/Animations/OrbitImages/OrbitImages.tsx @@ -1,7 +1,7 @@ // Component created by Dominik Koch // https://x.com/dominikkoch -import { useMemo, useEffect, useRef, useState, ReactNode } from 'react'; +import { useMemo, useEffect, useLayoutEffect, useRef, useState, ReactNode } from 'react'; import { motion, useMotionValue, useTransform, animate, MotionValue } from 'motion/react'; import './OrbitImages.css'; @@ -175,7 +175,7 @@ export default function OrbitImages({ responsive = false, }: OrbitImagesProps) { const containerRef = useRef(null); - const [scale, setScale] = useState(1); + const [scale, setScale] = useState(null); const designCenterX = baseWidth / 2; const designCenterY = baseWidth / 2; @@ -207,7 +207,7 @@ export default function OrbitImages({ } }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]); - useEffect(() => { + useLayoutEffect(() => { if (!responsive || !containerRef.current) return; const updateScale = () => { if (!containerRef.current) return; @@ -261,7 +261,8 @@ export default function OrbitImages({ style={{ width: responsive ? baseWidth : '100%', height: responsive ? baseWidth : '100%', - transform: responsive ? `translate(-50%, -50%) scale(${scale})` : undefined, + transform: responsive && scale !== null ? `translate(-50%, -50%) scale(${scale})` : undefined, + visibility: responsive && scale === null ? 'hidden' : undefined, }} >
- + )} diff --git a/src/ts-tailwind/Animations/OrbitImages/OrbitImages.tsx b/src/ts-tailwind/Animations/OrbitImages/OrbitImages.tsx index ea1229b4b..7c02d4c6c 100644 --- a/src/ts-tailwind/Animations/OrbitImages/OrbitImages.tsx +++ b/src/ts-tailwind/Animations/OrbitImages/OrbitImages.tsx @@ -1,7 +1,7 @@ // Component created by Dominik Koch // https://x.com/dominikkoch -import { useMemo, useEffect, useRef, useState, ReactNode } from 'react'; +import { useMemo, useEffect, useLayoutEffect, useRef, useState, ReactNode } from 'react'; import { motion, useMotionValue, useTransform, animate, MotionValue } from 'motion/react'; type OrbitShape = @@ -174,7 +174,7 @@ export default function OrbitImages({ responsive = false, }: OrbitImagesProps) { const containerRef = useRef(null); - const [scale, setScale] = useState(1); + const [scale, setScale] = useState(null); const designCenterX = baseWidth / 2; const designCenterY = baseWidth / 2; @@ -206,7 +206,7 @@ export default function OrbitImages({ } }, [shape, customPath, designCenterX, designCenterY, radiusX, radiusY, radius, starPoints, starInnerRatio]); - useEffect(() => { + useLayoutEffect(() => { if (!responsive || !containerRef.current) return; const updateScale = () => { if (!containerRef.current) return; @@ -260,7 +260,8 @@ export default function OrbitImages({ style={{ width: responsive ? baseWidth : '100%', height: responsive ? baseWidth : '100%', - transform: responsive ? `translate(-50%, -50%) scale(${scale})` : undefined, + transform: responsive && scale !== null ? `translate(-50%, -50%) scale(${scale})` : undefined, + visibility: responsive && scale === null ? 'hidden' : undefined, transformOrigin: 'center center', }} > @@ -278,7 +279,7 @@ export default function OrbitImages({ viewBox={`0 0 ${baseWidth} ${baseWidth}`} className="absolute inset-0 pointer-events-none" > - + )}