con un clic
3d-design-system
Implement 3D elements and effects using Three.js and React Three Fiber
Menú
Implement 3D elements and effects using Three.js and React Three Fiber
Guidelines for applying Disney's 12 principles of animation to web interfaces. Use when implementing motion, reviewing animation quality, or designing micro-interactions. Triggers on tasks involving CSS animations, transitions, motion libraries, or UX feedback.
Plan, validate, and use 1Password CLI setup for secret injection and auth. Use when tasks need 1Password CLI usage, secret references, op run/read/inject, or provisioning secrets via env vars/.env files and scripts.
Apply 37signals/DHH Rails conventions when writing Ruby on Rails code. Use when building Rails applications, reviewing Rails code, or making architectural decisions. Covers various aspects of Rails application architecture, design and dependencies.
Expert 4PL and supply chain guidance for logistics operations. Use when discussing supply chain strategy, warehouse management, transportation planning, inventory optimization, 3PL partner management, logistics KPIs, or business strategy for logistics companies. Tailored for the eddication.io platform including DriverConnect driver tracking, job dispatch, and CRM operations.
Apply timeless programming wisdom from "97 Things Every Programmer Should Know" when writing, reviewing, or refactoring code. Use for design decisions, code quality checks, professional development guidance, testing strategies, and workflow optimization.
On-demand A2UI templates for flowchart, form, dashboard, info cards, and gallery.
| name | 3D Design System |
| description | Implement 3D elements and effects using Three.js and React Three Fiber |
Create immersive 3D poker experiences using React Three Fiber, Three.js, and CSS 3D transforms.
npm install three @react-three/fiber @react-three/drei
import { Canvas } from '@react-three/fiber';
import { OrbitControls, PerspectiveCamera } from '@react-three/drei';
function PokerScene() {
return (
<Canvas>
<PerspectiveCamera makeDefault position={[0, 5, 10]} />
<OrbitControls enablePan={false} maxPolarAngle={Math.PI / 2.5} />
{/* Lighting */}
<ambientLight intensity={0.4} />
<spotLight position={[0, 10, 0]} intensity={0.8} castShadow />
{/* Scene Objects */}
<PokerTable3D />
<Cards3D />
<Chips3D />
</Canvas>
);
}
import { useGLTF, MeshReflectorMaterial } from '@react-three/drei';
function PokerTable3D() {
return (
<group>
{/* Felt surface */}
<mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, 0, 0]} receiveShadow>
<planeGeometry args={[12, 6]} />
<meshStandardMaterial
color="#0d4d33"
roughness={0.9}
metalness={0.1}
/>
</mesh>
{/* Rail */}
<mesh position={[0, 0.2, 0]}>
<torusGeometry args={[5, 0.3, 16, 100]} />
<meshStandardMaterial
color="#8B4513"
roughness={0.3}
metalness={0.6}
/>
</mesh>
{/* Floor with reflections */}
<mesh rotation={[-Math.PI / 2, 0, 0]} position={[0, -0.5, 0]}>
<planeGeometry args={[50, 50]} />
<MeshReflectorMaterial
blur={[300, 100]}
resolution={1024}
mixBlur={1}
mixStrength={40}
roughness={1}
depthScale={1.2}
color="#101010"
metalness={0.4}
/>
</mesh>
</group>
);
}
import { useTexture } from '@react-three/drei';
import { useSpring, animated } from '@react-spring/three';
function Card3D({ card, position, rotation, isFlipped }) {
const [frontTexture, backTexture] = useTexture([
`/cards/${card}.png`,
'/cards/back.png'
]);
const { rotateY } = useSpring({
rotateY: isFlipped ? Math.PI : 0,
config: { mass: 1, tension: 180, friction: 12 }
});
return (
<animated.group position={position} rotation-y={rotateY}>
{/* Front face */}
<mesh rotation={[0, 0, 0]}>
<planeGeometry args={[0.7, 1]} />
<meshStandardMaterial map={frontTexture} />
</mesh>
{/* Back face */}
<mesh rotation={[0, Math.PI, 0]}>
<planeGeometry args={[0.7, 1]} />
<meshStandardMaterial map={backTexture} />
</mesh>
</animated.group>
);
}
import { useFrame } from '@react-three/fiber';
import { useRef } from 'react';
function DealingCard3D({ targetPosition, delay }) {
const ref = useRef();
const [isDealing, setIsDealing] = useState(false);
useEffect(() => {
const timer = setTimeout(() => setIsDealing(true), delay * 100);
return () => clearTimeout(timer);
}, [delay]);
useFrame((state, delta) => {
if (!ref.current || !isDealing) return;
ref.current.position.lerp(targetPosition, 0.1);
ref.current.rotation.y += delta * 2;
});
return (
<mesh ref={ref} position={[0, 5, 0]}>
<planeGeometry args={[0.7, 1]} />
<meshStandardMaterial color="red" />
</mesh>
);
}
function ChipStack3D({ amount, position, color = '#ff4444' }) {
const chipCount = Math.min(Math.ceil(amount / 100), 10);
return (
<group position={position}>
{[...Array(chipCount)].map((_, i) => (
<mesh key={i} position={[0, i * 0.05, 0]} castShadow>
<cylinderGeometry args={[0.3, 0.3, 0.04, 32]} />
<meshStandardMaterial
color={color}
roughness={0.3}
metalness={0.7}
/>
</mesh>
))}
</group>
);
}
import { useSpring, animated } from '@react-spring/three';
function FlyingChip3D({ from, to, onComplete }) {
const { position, rotation } = useSpring({
from: { position: from, rotation: [0, 0, 0] },
to: { position: to, rotation: [Math.PI * 2, Math.PI * 4, 0] },
config: { mass: 1, tension: 200, friction: 20 },
onRest: onComplete
});
return (
<animated.mesh position={position} rotation={rotation}>
<cylinderGeometry args={[0.3, 0.3, 0.04, 32]} />
<meshStandardMaterial color="#ffd700" metalness={0.8} roughness={0.2} />
</animated.mesh>
);
}
.card-3d {
perspective: 1000px;
transform-style: preserve-3d;
}
.card-3d:hover {
transform: rotateY(15deg) rotateX(-5deg);
}
.card-3d-inner {
transition: transform 0.6s;
transform-style: preserve-3d;
}
.card-3d.flipped .card-3d-inner {
transform: rotateY(180deg);
}
.card-front, .card-back {
position: absolute;
backface-visibility: hidden;
}
.card-back {
transform: rotateY(180deg);
}
.btn-3d {
transform: perspective(500px) translateZ(0);
transition: transform 0.2s, box-shadow 0.2s;
}
.btn-3d:hover {
transform: perspective(500px) translateZ(20px);
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4);
}
.btn-3d:active {
transform: perspective(500px) translateZ(-10px);
}
import { Environment } from '@react-three/drei';
<Environment
preset="night" // 'sunset', 'dawn', 'night', 'warehouse', 'forest', etc.
background={false}
/>
function PokerLighting() {
return (
<>
{/* Main overhead light */}
<spotLight
position={[0, 10, 0]}
angle={0.5}
penumbra={0.5}
intensity={1}
castShadow
shadow-mapSize={[2048, 2048]}
/>
{/* Rim lights */}
<pointLight position={[10, 5, 0]} intensity={0.3} color="#ff7700" />
<pointLight position={[-10, 5, 0]} intensity={0.3} color="#0077ff" />
{/* Ambient fill */}
<ambientLight intensity={0.2} />
</>
);
}
instancedMesh for many identical objectsfunction ChipField({ chips }) {
const meshRef = useRef();
useEffect(() => {
chips.forEach((chip, i) => {
meshRef.current.setMatrixAt(i, new Matrix4().makeTranslation(...chip.position));
});
meshRef.current.instanceMatrix.needsUpdate = true;
}, [chips]);
return (
<instancedMesh ref={meshRef} args={[null, null, chips.length]}>
<cylinderGeometry args={[0.3, 0.3, 0.04, 16]} />
<meshStandardMaterial color="#ffd700" />
</instancedMesh>
);
}
useLoader for async loadingconst texture = useLoader(TextureLoader, '/texture.jpg');
const Poker3DScene = dynamic(() => import('./Poker3DScene'), {
ssr: false,
loading: () => <LoadingSpinner />
});
import { LOD } from 'three';
// Simpler geometry at distance, detailed up close