Threejs创建一个可旋转拖动自动运行的小车
- 2023-04-22 06:12:00
- pjd
- 原创 364
1、创建项目(Vite为例)
npm create vite <项目名称> $ npm create vite threejs-1 ? Select a framework: » - Use arrow-keys. Return to submit. > Vanilla Vue React Preact Lit Svelte Others Done. Now run: cd threejs-1 npm install npm run dev
2、安装依赖
npm install vite three
3、启动项目
npm run dev > threejs-1@0.0.0 dev > vite VITE v4.3.1 ready in 445 ms ➜ Local: http://127.0.0.1:5173/ ➜ Network: use --host to expose ➜ press h to show help
4、引入THREE 到main.js文件中
import * as THREE from "three" console.log(THREE)
立方体示例代码:
import * as THREE from "three" import Stat from "three/examples/jsm/libs/stats.module" import { OrbitControls } from "three/examples/jsm/controls/OrbitControls" const w = window.innerWidth const h = window.innerHeight const stat = new Stat() const scene = new THREE.Scene() scene.add(new THREE.AxesHelper(2,2,2)) const g = new THREE.BoxGeometry(1,1,1) const m = new THREE.MeshNormalMaterial() const cube = new THREE.Mesh(g,m) scene.add(cube) const light = new THREE.AmbientLight() scene.add(light) const camera = new THREE.PerspectiveCamera(75, w/h,0.1,100) camera.position.set(0,0,5) camera.lookAt(0,0,0) const renderer = new THREE.WebGLRenderer() renderer.setSize(w,h) document.body.append(renderer.domElement) document.body.append(stat.dom) const orbitControl = new OrbitControls(camera,renderer.domElement) const clock = new THREE.Clock() tick() function tick() { //const time = clock.getElapsedTime() requestAnimationFrame(tick) renderer.render(scene,camera) stat.update() orbitControl.update() }
效果如下:
5、小车运行示例
import * as THREE from "three"; import Stat from "three/examples/jsm/libs/stats.module"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls"; import { AxesHelper } from "three"; import * as dat from "dat.gui"; import t1 from './img/floor.jpeg' import c1 from './img/color1.jpeg' import c2 from './img/color2.jpg' import black from './img/black.jpg' let w = window.innerWidth; let h = window.innerHeight; const stat = new Stat(); const gui = new dat.GUI(); const scene = new THREE.Scene(); const material = new THREE.MeshNormalMaterial(); // scene.add(new AxesHelper(15, 15, 15)); //材质 const loader = new THREE.TextureLoader() const texture = loader.load(t1) // texture.magFilter = THREE.NearestFilter // texture.wrapS = THREE.RepeatWrapping // texture.wrapT = THREE.RepeatWrapping // texture.repeat.set(10,10) //地面 const planeG = new THREE.PlaneGeometry(30, 30); const m = new THREE.MeshBasicMaterial({ // color: 0xcccccc, map:texture, side: THREE.DoubleSide, }); const plane = new THREE.Mesh(planeG, m); plane.rotation.x = -Math.PI / 2; plane.position.y = -1.2; scene.add(plane); //汽车 const car = new THREE.Group(); //前轮 const frontWheels = new THREE.Group(); const frontWheel1 = new THREE.Group(); const frontWheelG = new THREE.TorusGeometry(1, 0.2); const wheelTexture = loader.load('black') const wheelMaterial = new THREE.MeshStandardMaterial({ map:wheelTexture }) const frontWheel = new THREE.Mesh(frontWheelG, wheelMaterial); //轮毂 const frontHubGroup = new THREE.Group(); let n = 10; for (let i = 0; i < n; i++) { const frontHubG = new THREE.CylinderGeometry(0.1, 0.1, 2); const frontHub = new THREE.Mesh(frontHubG, material); frontHub.rotation.z = ((2 * Math.PI) / n) * i; frontHubGroup.add(frontHub); } //轮轴 let len = 5; const frontAxleG = new THREE.CylinderGeometry(0.2, 0.2, len); const frontAxle = new THREE.Mesh(frontAxleG, material); frontAxle.rotation.x = -0.5 * Math.PI; frontAxle.position.z = -len / 2; frontWheel1.add(frontWheel, frontHubGroup); const frontWheel2 = frontWheel1.clone(); frontWheel2.position.z = -len; frontWheels.add(frontWheel1, frontWheel2, frontAxle); frontWheels.position.z = len / 2; frontWheels.position.x = -len / 2; const backWheels = frontWheels.clone(); backWheels.position.x = len / 2; // 车体 const body = new THREE.Group(); const bodyG1 = new THREE.BoxGeometry(10, 1.2, 4); //车体材质 const bodyTexture1 = loader.load(c1) const bodymaterial1 = new THREE.MeshStandardMaterial({ map:bodyTexture1 }) const bodyTexture2 = loader.load(c2) const bodymaterial2 = new THREE.MeshStandardMaterial({ map:bodyTexture2 }) const bodyBottom = new THREE.Mesh(bodyG1, bodymaterial2); //车顶 ///////////////////////////////////////////// const height = 4, width = 2; const shape = new THREE.Shape(); shape.moveTo(0, 0); shape.lineTo(0, width); shape.lineTo(height, width); shape.lineTo(height, 0); shape.lineTo(0, 0); const extrudeSettings = { steps: 2, depth: 0.1, bevelEnabled: true, bevelThickness: 1, bevelSize: 1, bevelOffset: 0, bevelSegments: 1, }; const roofgeometry = new THREE.ExtrudeGeometry(shape, extrudeSettings); //车顶材质 const roofmesh = new THREE.Mesh(roofgeometry, bodymaterial2); roofmesh.rotation.x = 0.5 * Math.PI; roofmesh.position.x = -height / 2; roofmesh.position.z = -width / 2; roofmesh.position.y = width / 3; //////////////////////////////////////////// body.add(bodyBottom, roofmesh); car.add(frontWheels, backWheels, body); //灯光 const light = new THREE.AmbientLight(); scene.add(car, light); //像机 const camera = new THREE.PerspectiveCamera(75, w / h, 0.1, 100); camera.position.set(0, 2, 20); camera.lookAt(0, 0, 0); const guiFolder1 = gui.addFolder("相机位置"); guiFolder1.add(camera.position, "x", -20, 20, 0.01).name("相机x轴位置"); guiFolder1.add(camera.position, "y", -20, 20, 0.01).name("相机y轴位置"); guiFolder1.add(camera.position, "z", -20, 20, 0.01).name("相机z轴位置"); const guiFolder2 = gui.addFolder("汽车位置"); guiFolder2.add(car.position, "x", -20, 20, 0.01).name("汽车x轴位置"); guiFolder2.add(car.position, "y", -20, 20, 0.01).name("汽车y轴位置"); guiFolder2.add(car.position, "z", -20, 20, 0.01).name("汽车z轴位置"); //渲染器 const renderer = new THREE.WebGLRenderer(); renderer.setSize(w, h); renderer.setClearColor(0x79deec); document.body.append(renderer.domElement); document.body.append(stat.dom); const orbitControls = new OrbitControls(camera, renderer.domElement); const clock = new THREE.Clock(); tick(); function tick() { const time = clock.getElapsedTime(); frontWheels.rotation.z = time; backWheels.rotation.z = time; car.position.x = -time % 10; requestAnimationFrame(tick); renderer.render(scene, camera); // orbitControls.update(); stat.update(); } //窗口自适应大小 window.addEventListener("resize", () => { w = window.innerWidth; h = window.innerHeight; //camera camera.aspect = w / h; camera.updateProjectionMatrix(); //renderer renderer.setSize(w, h); });
效果如下: