131 lines
3.6 KiB
JavaScript

import * as THREE from 'three'
const scene = new THREE.Scene()
scene.background = new THREE.Color(0xf3f5f8)
const camera = new THREE.PerspectiveCamera(
55,
window.innerWidth / window.innerHeight,
0.1,
100
)
camera.position.set(0, 2, 7)
camera.lookAt(0, 0, 0)
const renderer = new THREE.WebGLRenderer({ antialias: true })
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
scene.add(new THREE.AmbientLight(0xffffff, 0.9))
const keyLight = new THREE.DirectionalLight(0xffffff, 1)
keyLight.position.set(3, 4, 5)
scene.add(keyLight)
const objects = {
center: new THREE.Mesh(
new THREE.BoxGeometry(1.2, 1.2, 1.2),
new THREE.MeshStandardMaterial({ color: 0x2a9d8f })
),
left: new THREE.Mesh(
new THREE.BoxGeometry(0.9, 0.9, 0.9),
new THREE.MeshStandardMaterial({ color: 0xe76f51 })
),
right: new THREE.Mesh(
new THREE.BoxGeometry(0.9, 0.9, 0.9),
new THREE.MeshStandardMaterial({ color: 0x457b9d })
),
}
scene.add(objects.center, objects.left, objects.right)
const states = {
state1: {
center: { position: [0, 0, 0], rotation: [0, 0, 0], visible: true },
left: { position: [0, 0, 0], rotation: [0, 0, 0], visible: false },
right: { position: [0, 0, 0], rotation: [0, 0, 0], visible: false },
},
state2: {
center: { position: [0, 0, 0], rotation: [0.25, 0.4, 0], visible: true },
left: { position: [-2.1, 0, 0.2], rotation: [0, 0.2, 0], visible: true },
right: { position: [2.1, 0, -0.2], rotation: [0, -0.2, 0], visible: true },
},
state3: {
center: { position: [0, 1.3, 0], rotation: [0.6, 0.9, 0], visible: true },
left: { position: [-1.2, -1, 1.2], rotation: [0.3, 0.3, 0.1], visible: true },
right: { position: [0, 0, 0], rotation: [0, 0, 0], visible: false },
},
}
const targets = {
center: { position: new THREE.Vector3(), rotation: new THREE.Euler() },
left: { position: new THREE.Vector3(), rotation: new THREE.Euler() },
right: { position: new THREE.Vector3(), rotation: new THREE.Euler() },
}
const buttons = Array.from(document.querySelectorAll('.state-btn'))
let activeState = 'state1'
function updateButtonState(stateName) {
buttons.forEach((button) => {
button.classList.toggle('active', button.dataset.state === stateName)
})
}
function applyState(stateName) {
const nextState = states[stateName]
if (!nextState) {
return
}
activeState = stateName
Object.keys(objects).forEach((name) => {
const object = objects[name]
const config = nextState[name]
targets[name].position.set(...config.position)
targets[name].rotation.set(...config.rotation)
object.visible = config.visible
})
updateButtonState(stateName)
}
buttons.forEach((button) => {
button.addEventListener('click', () => {
applyState(button.dataset.state)
})
})
window.addEventListener('keydown', (event) => {
if (event.key === '1') applyState('state1')
if (event.key === '2') applyState('state2')
if (event.key === '3') applyState('state3')
})
applyState(activeState)
function animate() {
Object.keys(objects).forEach((name) => {
const object = objects[name]
const target = targets[name]
object.position.lerp(target.position, 0.1)
object.rotation.x += (target.rotation.x - object.rotation.x) * 0.1
object.rotation.y += (target.rotation.y - object.rotation.y) * 0.1
object.rotation.z += (target.rotation.z - object.rotation.z) * 0.1
})
renderer.render(scene, camera)
}
renderer.setAnimationLoop(animate)
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})