{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "Antigravity-TS-CSS", "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.tsx", "content": "import { Canvas, useFrame, useThree } from '@react-three/fiber';\nimport React, { useMemo, useRef } from 'react';\nimport * as THREE from 'three';\n\ninterface AntigravityProps {\n count?: number;\n magnetRadius?: number;\n ringRadius?: number;\n waveSpeed?: number;\n waveAmplitude?: number;\n particleSize?: number;\n lerpSpeed?: number;\n color?: string;\n autoAnimate?: boolean;\n particleVariance?: number;\n rotationSpeed?: number;\n depthFactor?: number;\n pulseSpeed?: number;\n particleShape?: 'capsule' | 'sphere' | 'box' | 'tetrahedron';\n fieldStrength?: number;\n}\n\nconst AntigravityInner: React.FC = ({\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: React.FC = props => {\n return (\n \n \n \n );\n};\n\nexport default Antigravity;\n" } ], "registryDependencies": [], "dependencies": [ "@react-three/fiber@^9.3.0", "three@^0.167.1" ] }