1、一个简单的 demo

import * as THREE from 'three'
import { PerspectiveCamera, AxesHelper, Scene, WebGLRenderer, TextureLoader, BoxGeometry, MeshBasicMaterial } from "three"
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { Tween, Easing } from '@tweenjs/tween.js'
import bgc from './public/bgc.jpg'
let scene, camera, renderer, controls, mesh, tween;
function initScene() {
scene = new Scene()
}
function initCamera() {
camera = new PerspectiveCamera(45, window.innerWidth/window.innerHeight, 0.1, 1000)
camera.position.z = 8
}
function initRenderer() {
renderer = new WebGLRenderer({
antialias: true
})
renderer.setSize(window.innerWidth, window.innerHeight)
document.body.appendChild(renderer.domElement)
}
function initAxesHelper() {
const axesHelper = new AxesHelper(5)
scene.add(axesHelper)
}
function initOrbitControls() {
controls = new OrbitControls(camera, renderer.domElement)
}
function initMesh() {
const geometry = new BoxGeometry(1,1,1)
const texture = new TextureLoader().load(bgc)
const material = new MeshBasicMaterial({
map: texture
})
mesh = new THREE.Mesh(geometry, material)
scene.add(mesh)
}
function init() {
initScene()
initCamera()
initRenderer()
initAxesHelper()
initOrbitControls()
initMesh()
const coords = {x: 0}
tween = new Tween(coords, false)
.to({x: 3}, 3000)
.easing(Easing.Quadratic.InOut)
.onUpdate((that) => {
mesh.position.x = that.x
})
.start()
}
init()
function render(time) {
renderer.render(scene, camera)
requestAnimationFrame(render)
tween.update(time)
}
render()
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})
2、3D汽车展厅

import {
PerspectiveCamera,
GridHelper,
Scene,
WebGLRenderer,
AmbientLight,
PlaneGeometry,
MeshPhysicalMaterial,
DoubleSide,
Mesh,
SpotLight,
CylinderGeometry,
Vector2,
Raycaster
} from "three"
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import GUI from 'lil-gui';
import { Tween, Easing } from '@tweenjs/tween.js'
import Lamborghini from "./public/20221017143009_parent_directory_货车04.gltf"
let scene, camera, renderer, controls, grid, tween, doorStatus = 'close';
let doors = []
let bodyMaterial = new MeshPhysicalMaterial({
color: "#d4e4fd",
metalness: 1,
roughness: 0.5,
clearcoat: 1,
clearcoatRoughness: 0.03
})
let glassMaterial = new MeshPhysicalMaterial({
color: "#4b4949",
metalness: 0.25,
roughness: 0,
transmission: 1
})
function initScene() {
scene = new Scene()
}
function initCamera() {
camera = new PerspectiveCamera(40, window.innerWidth/window.innerHeight, 0.1, 1000)
camera.position.set(4.25, 1.4, -4.5)
}
function initRenderer() {
renderer = new WebGLRenderer({
antialias: true
})
renderer.setSize(window.innerWidth, window.innerHeight)
renderer.shadowMap.enabled = true
document.body.appendChild(renderer.domElement)
}
function initOrbitControls() {
controls = new OrbitControls(camera, renderer.domElement)
controls.enableDamping = true
controls.minPolarAngle = 0;
controls.maxPolarAngle = 80 / 360 * 2 * Math.PI;
}
function initGridHelper() {
grid = new GridHelper(20, 40, 'red', 0xffffff)
grid.material.opacity = 0.5
grid.material.transparent = true
scene.add(grid)
}
function loadCarModel() {
new GLTFLoader().load(Lamborghini, (gltf) => {
const carModel = gltf.scene
console.log(carModel)
carModel.rotation.y = Math.PI
carModel.traverse(obj => {
if(obj.name === 'che001_1' || obj.name === 'che001_4' || obj.name === 'che001_2' || obj.name === 'che001_6' || obj.name === 'che001_7') {
obj.material = bodyMaterial
}
if (obj.name === 'che001_10' || obj.name === 'che001_11' || obj.name === 'che001_12' || obj.name === 'che001_13') {
obj.material = glassMaterial
}
if(obj.name === 'che001_2') {
doors.push(obj)
}
obj.castShadow = true
})
scene.add(carModel)
})
}
function initAmbientLight() {
const ambientLight = new AmbientLight('#fff', 1)
scene.add(ambientLight)
}
function initFloor() {
const floorGeometry = new PlaneGeometry(20, 20)
const material = new MeshPhysicalMaterial({
side: DoubleSide,
color: 0x808080,
metalness: 0,
roughness: 0.1,
})
const mesh = new Mesh(floorGeometry, material)
mesh.rotation.x = Math.PI / 2
mesh.receiveShadow = true
scene.add(mesh)
}
function initSpotLight() {
const spotLight = new SpotLight(0xffffff, 800);
spotLight.angle = Math.PI / 8
spotLight.penumbra = 0.2
spotLight.decay = 2
spotLight.distance = 90
spotLight.shadow.radius = 10
spotLight.shadow.mapSize.set(4096, 4096)
spotLight.position.set(-5, 10, 1)
spotLight.target.position.set(0,0,0)
spotLight.castShadow = true
scene.add(spotLight)
}
function initCylinder() {
const geometry = new CylinderGeometry(12,12,20,32)
const material = new MeshPhysicalMaterial({
color: 0x6c6c6c,
side: DoubleSide
})
const cylinder = new Mesh(geometry, material)
scene.add(cylinder)
}
function initGui() {
const gui = new GUI();
let obj = {
bodyColor: '#d4e4fd',
glassColor: '#4b4949',
doorOpen,
doorClose,
carIn,
carOut
}
gui.addColor( obj, 'bodyColor').name('车身颜色').onChange(value => {
bodyMaterial.color.set(value)
});
gui.addColor( obj, 'glassColor').name('车窗颜色').onChange(value => {
glassMaterial.color.set(value)
});
gui.add(obj, 'doorOpen').name('打开车门')
gui.add(obj, 'doorClose').name('关闭车门')
gui.add(obj, 'carIn').name('车内视角')
gui.add(obj, 'carOut').name('车外视角')
}
function doorOpen() {
for(let index=0; index < doors.length; index ++) {
setAnimationDoor({y: 0}, { y: Math.PI / 3 }, doors[index])
}
doorStatus = 'open'
}
function doorClose() {
for(let index=0; index < doors.length; index ++) {
setAnimationDoor({ y: Math.PI / 3 }, {y: 0}, doors[index])
}
doorStatus = 'close'
}
function setAnimationDoor(start, end, mesh) {
tween = new Tween(start)
.to(end, 1000)
.easing(Easing.Quadratic.InOut)
.onUpdate((that) => {
mesh.rotation.y = that.y
})
.start()
}
function carIn() {
setAnimationCamera({cx: 4.25, cy: 1.4, cz: -4.5, ox: 0, oy: 0.5, oz: 0}, {cx: -0.27, ct: 0.83, cz: 0.6, ox: 0, oy: 0.5, oz: -3})
}
function carOut() {
setAnimationCamera({cx: -0.27, ct: 0.83, cz: 0.6, ox: 0, oy: 0.5, oz: -3}, {cx: 4.25, cy: 1.4, cz: -4.5, ox: 0, oy: 0.5, oz: 0})
}
function setAnimationCamera(start, end) {
tween = new Tween(start)
.to(end, 3000)
.easing(Easing.Quadratic.Out)
.onUpdate((that) => {
camera.position.set(that.cx, that.cy, that.cz)
controls.target.set(that.ox, that.oy, that.oz)
})
.start()
}
function init() {
initScene()
initCamera()
initRenderer()
initOrbitControls()
loadCarModel()
initAmbientLight()
initFloor()
initSpotLight()
initCylinder()
initGui()
}
init()
function render(time) {
renderer.render(scene, camera)
requestAnimationFrame(render)
controls.update()
tween && tween.update(time)
}
render()
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight
camera.updateProjectionMatrix()
renderer.setSize(window.innerWidth, window.innerHeight)
})
window.addEventListener('click', onPointClick)
function onPointClick(event) {
let pointer = {}
pointer.x = (event.clientX / window.innerWidth) * 2 - 1
pointer.y = (event.clientY / window.innerHeight) * 2 - 1
let vector = new Vector2(pointer.x, pointer.y)
let raycaster = new Raycaster()
raycaster.setFromCamera(vector, camera)
let intersects = raycaster.intersectObjects(scene.children)
intersects.forEach(item => {
console.log(item.object)
if(item.object.name === 'che001_2') {
if(doorStatus === 'close') {
doorOpen()
} else {
doorClose()
}
console.log(intersects)
}
})
}