Phyllotaxis
threecn/phyllotaxisFreeComponent
A sunflower-style bloom of instanced petals placed by the golden angle, breathing from --primary at the core to --accent at the rim.
Install it
npx shadcn@latest add https://threecn.dev/r/phyllotaxis.jsonSource
1"use client"23import * as React from "react"4import { useFrame } from "@react-three/fiber"5import * as THREE from "three"67import {8 SceneContainer,9 type SceneContainerProps,10} from "@/components/threecn/scene-container"11import {12 useShadcnTheme,13 type ThemeMode,14} from "@/components/hooks/use-shadcn-theme"1516// The golden angle (137.5°) — the divergence angle sunflowers, pinecones and17// succulents use to pack seeds without gaps.18const GOLDEN_ANGLE = Math.PI * (3 - Math.sqrt(5))1920function Bloom({21 count,22 speed,23 spread,24 theme,25}: {26 count: number27 speed: number28 spread: number29 theme: ThemeMode30}) {31 const { primaryColor, accentColor } = useShadcnTheme(theme)32 const meshRef = React.useRef<THREE.InstancedMesh>(null)33 const groupRef = React.useRef<THREE.Group>(null)34 const dummy = React.useMemo(() => new THREE.Object3D(), [])35 const tmpColor = React.useMemo(() => new THREE.Color(), [])3637 // Fixed polar layout per seed (angle + normalized radius), computed once.38 const seeds = React.useMemo(() => {39 const arr = new Float32Array(count * 2)40 for (let i = 0; i < count; i++) {41 arr[i * 2] = i * GOLDEN_ANGLE42 arr[i * 2 + 1] = Math.sqrt(i / count) // 0 at center → 1 at rim43 }44 return arr45 }, [count])4647 useFrame(({ clock }) => {48 const mesh = meshRef.current49 if (!mesh) return50 const t = clock.getElapsedTime() * speed5152 for (let i = 0; i < count; i++) {53 const angle = seeds[i * 2]54 const rN = seeds[i * 2 + 1]55 const radius = rN * spread56 const x = Math.cos(angle) * radius57 const z = Math.sin(angle) * radius58 // The whole disc breathes; outer petals lift a touch more.59 const y = Math.sin(t * 1.4 - rN * 6) * 0.25 * (0.4 + rN)6061 dummy.position.set(x, y, z)62 // Petals tilt outward and face the sky, scaling down toward the rim.63 dummy.rotation.set(Math.PI / 2 - rN * 0.9, -angle, 0)64 const s = 0.12 + (1 - rN) * 0.1665 dummy.scale.set(s, s * 2.2, s)66 dummy.updateMatrix()67 mesh.setMatrixAt(i, dummy.matrix)6869 // Center → --primary, rim → --accent.70 tmpColor.copy(primaryColor).lerp(accentColor, rN)71 mesh.setColorAt(i, tmpColor)72 }73 mesh.instanceMatrix.needsUpdate = true74 if (mesh.instanceColor) mesh.instanceColor.needsUpdate = true7576 if (groupRef.current) groupRef.current.rotation.y = t * 0.1577 })7879 return (80 <group ref={groupRef}>81 <instancedMesh82 key={count}83 ref={meshRef}84// … truncated
What it pulls in
npm packages
Files it writes
More from threecn
All 28 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| AuroraRibbonsaurora-ribbons | threecn | Components | Free | 3 deps · 3 files | |
| Boidsboids | threecn | Components | Free | 3 deps · 3 files | |
| Clothcloth | threecn | Components | Free | 3 deps · 3 files | |
| Crystalcrystal | threecn | Components | Free | 3 deps · 3 files | |
| CubeWavecube-wave | threecn | Components | Free | 3 deps · 3 files | |
| CurlFlowcurl-flow | threecn | Components | Free | 3 deps · 3 files | |
| DnaHelixdna-helix | threecn | Components | Free | 3 deps · 3 files | |
| FloatingCard3Dfloating-card-3d | threecn | Components | Free | 3 deps · 3 files |
