教你如何使用THREEJS實現(xiàn)一個可調(diào)節(jié)檔位、可搖頭的電風(fēng)扇
夏天到了,用Three.js
實現(xiàn)一個可以搖頭和調(diào)節(jié)檔位的電風(fēng)扇。主要使用到Blender
處理3D模型,用Vite
+Typescript
搭建項目框架。效果演示:
一、處理模型
1、從愛(bai)給(gei)網(wǎng)下載一個風(fēng)扇的3D模型,在Blender中打開,給模型貼上圖。
2、拆解模型。將風(fēng)扇模型拆解成按鈕、底座、扇葉、頭部四個部分,其中按鈕共五個,包括四個檔位和一個搖頭的開關(guān)。
3、導(dǎo)出模型。導(dǎo)出GLTF
格式模型。
二、場景搭建
1、初始化場景
this.scene = new THREE.Scene(); /** 攝像機 */ this.camera = new THREE.PerspectiveCamera(75, this.sizes.width / this.sizes.height, 0.1, 100); this.camera.position.set(0, 0.8, 1.8); /** 燈光 */ this.lightPoint = new THREE.HemisphereLight(0xffffff, 0xffffff, 1 ); this.lightPoint.position.set(0, 500, 0); this.scene.add(this.lightPoint); /** 控制器 */ this.controls = new OrbitControls(this.camera, this.renderer.domElement); this.controls.enableKeys = false; // 禁用按鍵 this.controls.enableZoom = false; // 禁用縮放 this.controls.enablePan = false; // 禁用拖拽 this.controls.maxPolarAngle = 1.3; // 最大垂直旋轉(zhuǎn)角度 this.controls.minPolarAngle = 1.3; // 最小垂直旋轉(zhuǎn)角度 this.controls.target = new THREE.Vector3(0, 0.8, 0);
2、加載模型
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; var gltf: GLTF = await new Promise((resolve, _) => new GLTFLoader().load('./fan.glb', gltf => resolve(gltf))); this.scene.add(gltf.scene);
3、綁定風(fēng)扇按鈕
this.fan = new Fan(gltf); /** 檔位調(diào)節(jié)按鈕 */ let btns: Array<[string, Level]> = [ ['Btn_1', Level.one], ['Btn_2', Level.two], ['Btn_3', Level.three], ['Btn_4', Level.zero], ]; btns.forEach(([name, level]) => { let btn = gltf.scene.getObjectByName(name); if (btn) this.fan.btns.push(new LevelBtn(btn, level)); }); /** 搖頭按鈕 */ let btn = gltf.scene.getObjectByName("Shake"); if (btn) this.fan.btns.push(new ShakeBtn(btn));
三、功能實現(xiàn)
1、扇葉旋轉(zhuǎn)
function update() { let leaf = this.obj.scene.getObjectByName("Leaf"); let rotationY = leaf!.rotation.y + Math.PI/10 * this.speed; while(rotationY > Math.PI * 2) rotationY = rotationY - Math.PI * 2; leaf!.rotation.y = rotationY; requestAnimationFrame(() => update()); }
2、檔位調(diào)節(jié)
import { gsap } from 'gsap'; function turnLevel(btn: LevelBtn) { if(btn.state == BtnState.down) return; this.btns.filter(item => item instanceof LevelBtn).forEach(item => item.up()); btn.down(); if(btn.level !== Level.zero) this.state = State.on; this.level = btn.level; gsap.to(this, 3, { speed: this.level }); }
3、左右搖頭
let head = this.obj.scene.getObjectByName("Head"); let shake = this.obj.scene.getObjectByName("Shake"); let leaf = this.obj.scene.getObjectByName("Leaf"); let rotationZ = head!.rotation.z + Math.PI / 1000 * this.shakeDir; if(Math.abs(rotationZ) > Math.abs(this.shakeRange)) { let shakeDir = this.shakeDir; setTimeout(() => { if(shakeDir == ShakeDir.left) this.shakeDir = ShakeDir.right; else if(shakeDir == ShakeDir.right) this.shakeDir = ShakeDir.left; }, 1000) this.shakeDir = ShakeDir.wait; rotationZ = Math.abs(this.shakeRange) * Math.abs(rotationZ) / rotationZ; } head!.rotation.z = rotationZ; leaf!.rotation.z = rotationZ; shake!.rotation.z = rotationZ;
四、最后
項目代碼和演示地址:https://codesandbox.io/p/sandbox/threejs-mini-fans-dx6nm6
到此這篇關(guān)于使用THREEJS實現(xiàn)一個可調(diào)節(jié)檔位、可搖頭的電風(fēng)扇的文章就介紹到這了,更多相關(guān)threejs可調(diào)節(jié)檔位、可搖頭的電風(fēng)扇內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript四種調(diào)用模式和this示例介紹
JavaScript調(diào)用時除了聲明時定義的形參外,每個函數(shù)接受兩個附加參數(shù):this 和arguments,下面為大家介紹下JavaScript四種調(diào)用模式和this2014-01-01js實現(xiàn)百度聯(lián)盟中一款不錯的圖片切換效果完整實例
這篇文章主要介紹了js實現(xiàn)百度聯(lián)盟中一款不錯的圖片切換效果的方法,以完整實例形式分析了javascript操作圖片切換的技巧,需要的朋友可以參考下2015-03-03javascript拖曳互換div的位置實現(xiàn)示例
一個div拖動互換位置的demo,還有很大優(yōu)化的空間,利用dom元素的dragstart/ondragover/ondrop事件完成,感興趣的可以了解一下2021-06-06