{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "Antigravity-JS-TW",
"title": "Antigravity",
"description": "3D antigravity particle field that repels from the cursor with smooth motion.",
"type": "registry:component",
"files": [
{
"type": "registry:component",
"path": "Antigravity/Antigravity.jsx",
"content": "/* eslint-disable react/no-unknown-property */\nimport { Canvas, useFrame, useThree } from '@react-three/fiber';\nimport { useMemo, useRef } from 'react';\nimport * as THREE from 'three';\n\nconst AntigravityInner = ({\n count = 300,\n magnetRadius = 10,\n ringRadius = 10,\n waveSpeed = 0.4,\n waveAmplitude = 1,\n particleSize = 2,\n lerpSpeed = 0.1,\n color = '#FF9FFC',\n autoAnimate = false,\n particleVariance = 1,\n rotationSpeed = 0,\n depthFactor = 1,\n pulseSpeed = 3,\n particleShape = 'capsule',\n fieldStrength = 10\n}) => {\n const meshRef = useRef(null);\n const { viewport } = useThree();\n const dummy = useMemo(() => new THREE.Object3D(), []);\n\n const lastMousePos = useRef({ x: 0, y: 0 });\n const lastMouseMoveTime = useRef(0);\n const virtualMouse = useRef({ x: 0, y: 0 });\n\n const particles = useMemo(() => {\n const temp = [];\n const width = viewport.width || 100;\n const height = viewport.height || 100;\n\n for (let i = 0; i < count; i++) {\n const t = Math.random() * 100;\n const factor = 20 + Math.random() * 100;\n const speed = 0.01 + Math.random() / 200;\n const xFactor = -50 + Math.random() * 100;\n const yFactor = -50 + Math.random() * 100;\n const zFactor = -50 + Math.random() * 100;\n\n const x = (Math.random() - 0.5) * width;\n const y = (Math.random() - 0.5) * height;\n const z = (Math.random() - 0.5) * 20;\n\n const randomRadiusOffset = (Math.random() - 0.5) * 2;\n\n temp.push({\n t,\n factor,\n speed,\n xFactor,\n yFactor,\n zFactor,\n mx: x,\n my: y,\n mz: z,\n cx: x,\n cy: y,\n cz: z,\n vx: 0,\n vy: 0,\n vz: 0,\n randomRadiusOffset\n });\n }\n return temp;\n }, [count, viewport.width, viewport.height]);\n\n useFrame(state => {\n const mesh = meshRef.current;\n if (!mesh) return;\n\n const { viewport: v, pointer: m } = state;\n\n const mouseDist = Math.sqrt(Math.pow(m.x - lastMousePos.current.x, 2) + Math.pow(m.y - lastMousePos.current.y, 2));\n\n if (mouseDist > 0.001) {\n lastMouseMoveTime.current = Date.now();\n lastMousePos.current = { x: m.x, y: m.y };\n }\n\n let destX = (m.x * v.width) / 2;\n let destY = (m.y * v.height) / 2;\n\n if (autoAnimate && Date.now() - lastMouseMoveTime.current > 2000) {\n const time = state.clock.getElapsedTime();\n destX = Math.sin(time * 0.5) * (v.width / 4);\n destY = Math.cos(time * 0.5 * 2) * (v.height / 4);\n }\n\n const smoothFactor = 0.05;\n virtualMouse.current.x += (destX - virtualMouse.current.x) * smoothFactor;\n virtualMouse.current.y += (destY - virtualMouse.current.y) * smoothFactor;\n\n const targetX = virtualMouse.current.x;\n const targetY = virtualMouse.current.y;\n\n const globalRotation = state.clock.getElapsedTime() * rotationSpeed;\n\n particles.forEach((particle, i) => {\n let { t, speed, mx, my, mz, cz, randomRadiusOffset } = particle;\n\n t = particle.t += speed / 2;\n\n const projectionFactor = 1 - cz / 50;\n const projectedTargetX = targetX * projectionFactor;\n const projectedTargetY = targetY * projectionFactor;\n\n const dx = mx - projectedTargetX;\n const dy = my - projectedTargetY;\n const dist = Math.sqrt(dx * dx + dy * dy);\n\n let targetPos = { x: mx, y: my, z: mz * depthFactor };\n\n if (dist < magnetRadius) {\n const angle = Math.atan2(dy, dx) + globalRotation;\n\n const wave = Math.sin(t * waveSpeed + angle) * (0.5 * waveAmplitude);\n const deviation = randomRadiusOffset * (5 / (fieldStrength + 0.1));\n\n const currentRingRadius = ringRadius + wave + deviation;\n\n targetPos.x = projectedTargetX + currentRingRadius * Math.cos(angle);\n targetPos.y = projectedTargetY + currentRingRadius * Math.sin(angle);\n targetPos.z = mz * depthFactor + Math.sin(t) * (1 * waveAmplitude * depthFactor);\n }\n\n particle.cx += (targetPos.x - particle.cx) * lerpSpeed;\n particle.cy += (targetPos.y - particle.cy) * lerpSpeed;\n particle.cz += (targetPos.z - particle.cz) * lerpSpeed;\n\n dummy.position.set(particle.cx, particle.cy, particle.cz);\n\n dummy.lookAt(projectedTargetX, projectedTargetY, particle.cz);\n dummy.rotateX(Math.PI / 2);\n\n const currentDistToMouse = Math.sqrt(\n Math.pow(particle.cx - projectedTargetX, 2) + Math.pow(particle.cy - projectedTargetY, 2)\n );\n\n const distFromRing = Math.abs(currentDistToMouse - ringRadius);\n let scaleFactor = 1 - distFromRing / 10;\n\n scaleFactor = Math.max(0, Math.min(1, scaleFactor));\n\n const finalScale = scaleFactor * (0.8 + Math.sin(t * pulseSpeed) * 0.2 * particleVariance) * particleSize;\n dummy.scale.set(finalScale, finalScale, finalScale);\n\n dummy.updateMatrix();\n\n mesh.setMatrixAt(i, dummy.matrix);\n });\n\n mesh.instanceMatrix.needsUpdate = true;\n });\n\n return (\n \n {particleShape === 'capsule' && }\n {particleShape === 'sphere' && }\n {particleShape === 'box' && }\n {particleShape === 'tetrahedron' && }\n \n \n );\n};\n\nconst Antigravity = props => {\n return (\n \n );\n};\n\nexport default Antigravity;\n"
}
],
"registryDependencies": [],
"dependencies": [
"@react-three/fiber@^9.3.0",
"three@^0.167.1"
]
}