JSFiddle - React, Tailwind, and code Playground
HTML
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three@0.170.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three@0.170.0/examples/jsm/"
}
}
</script>
CSS
body {
margin: 0;
overflow: hidden;
}
JavaScript
import * as THREE from "three"
const width = window.innerWidth,
height = window.innerHeight
// init
const camera = new THREE.PerspectiveCamera(70, width / height, 0.01, 1000)
camera.position.set(0, 5, 15)
camera.lookAt(new THREE.Vector3())
const scene = new THREE.Scene()
// init carousel ---------------------
const group = new THREE.Group()
const radius = 5
const count = 10
const planeWidth = 2
const planeHeight = 2
const angleStep = (2 * Math.PI) / count
const angleOffset = Math.PI / 2
for (let i = 0; i < count; i++) {
const geometry = new THREE.PlaneGeometry(planeWidth, planeHeight)
const material = new THREE.MeshBasicMaterial({
map: numberTexture(i),
side: THREE.DoubleSide,
})
const plane = new THREE.Mesh(geometry, material)
const angle = i * angleStep
const x = radius * Math.cos(angle)
const z = radius * Math.sin(angle)
plane.position.set(x, 0, z)
plane.lookAt(plane.position.clone().multiplyScalar(2))
group.add(plane)
}
group.rotation.y = -angleOffset
scene.add(group)
// Raycaster --------------
const raycaster = new THREE.Raycaster()
const mouse = new THREE.Vector2()
const targetQuat = new THREE.Quaternion()
const axis = new THREE.Vector3(0, 1, 0)
function onClick(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1
raycaster.setFromCamera(mouse, camera)
const intersects = raycaster.intersectObjects(group.children)
const angleStep = (2 * Math.PI) / count
if (intersects.length > 0) {
const clickedPlane = intersects[0].object
const planeIndex = group.children.indexOf(clickedPlane)
const angle = angleStep * planeIndex - angleOffset
targetQuat.setFromAxisAngle(axis, angle)
startRotation()
}
}
// --- Rotation animation
const duration = 1
const clock = new THREE.Clock()
let progress = 0
let rotate = false
function startRotation() {
rotate = true
progress = 0
clock.start()
}
function animateRotation() {
if...