泰国如何做网站推广,dw做网站基础,优化大师好用吗,企业域名如何申请项目搭建
本案例还是借助框架书写three项目#xff0c;借用vite构建工具搭建vue项目#xff0c;搭建完成之后#xff0c;用编辑器打开该项目#xff0c;在终端执行 npm i 安装一下依赖#xff0c;安装完成之后终端在安装 npm i three 即可。
因为我搭建的是vue3项目借用vite构建工具搭建vue项目搭建完成之后用编辑器打开该项目在终端执行 npm i 安装一下依赖安装完成之后终端在安装 npm i three 即可。
因为我搭建的是vue3项目为了便于代码的可读性所以我将three.js代码单独抽离放在一个组件当中在App根组件中进入引入该组件。具体如下
template!-- 3D汽车展厅 --CarShowroom/CarShowroom
/templatescript setup
import CarShowroom from ./components/CarShowroom.vue;
/scriptstyle langless*{margin: 0;padding: 0;}
/style初始化three.js代码
three.js开启必须用到的基础代码如下
导入three库
import * as THREE from three初始化场景
const scene new THREE.Scene()初始化相机
// 创建相机
const camera new THREE.PerspectiveCamera(40,window.innerWidth / window.innerHeight,0.1,1000)
camera.position.set(4.25,1.4,-4.5)初始化渲染器
// 创建渲染器
const renderer new THREE.WebGLRenderer({ antialias: true })
renderer.setSize(window.innerWidth,window.innerHeight)
document.body.appendChild(renderer.domElement)监听屏幕大小的改变修改渲染器的宽高和相机的比例
window.addEventListener(resize,(){ renderer.setSize(window.innerWidth,window.innerHeight)camera.aspect window.innerWidth/window.innerHeightcamera.updateProjectionMatrix()
})导入轨道控制器
// 添加轨道控制器
import { OrbitControls } from three/examples/jsm/controls/OrbitControls
// 添加控制器
const controls new OrbitControls(camera,renderer.domElement)
controls.enableDamping true // 设置控制阻尼设置渲染函数
// 设置渲染函数
const render (time) { controls.update()renderer.render(scene,camera)requestAnimationFrame(render)
}
render()ok写完基础代码之后接下来开始具体的Demo实操。
加载汽车模型
通过使用模型加载器GLTFLoader然后使用DRACOLoader加载Draco压缩过的模型可以显著减小模型文件体积从而加快加载速度和提高用户体验。代码如下
import { GLTFLoader } from three/examples/jsm/loaders/GLTFLoader;
import { DRACOLoader } from three/examples/jsm/loaders/DRACOLoader;// 加载汽车模型
const loader new GLTFLoader()
const dracoLoader new DRACOLoader()
dracoLoader.setDecoderPath(/draco/)
loader.setDRACOLoader(dracoLoader)
loader.load(/public/model/Lamborghini.glb,(gltf){scene.add(gltf.scene)
})复制代码模型加载完成画面如下因为没有灯光所以我们需要给一个灯光让模型展现出来这里设置一下环境光源
// 设置环境光源
const ambientLight new THREE.AmbientLight(#fff,0.5)
scene.add(ambientLight)设置展厅效果
这里通过three库中自带的一些模型来实现展厅的效果如下
设置地板样式
// 设置地板样式
const floorGeometry new THREE.PlaneGeometry(20,20)
const floormaterial new THREE.MeshPhysicalMaterial({side: THREE.DoubleSide,color: 0x808080,metalness: 0, // 设置金属度roughness: 0.1, // 设置粗糙度wireframe: false // 关闭网格线
})
const mesh new THREE.Mesh(floorGeometry,floormaterial)
mesh.rotation.x Math.PI / 2
scene.add(mesh)底部样式设置完设置一个圆柱体将整个地板进行包裹
// 设置圆柱体模拟展厅
const cylinder new THREE.CylinderGeometry(12,12,20,32)
const cylindermaterial new THREE.MeshPhysicalMaterial({color: 0x6c6c6c,side: THREE.DoubleSide
})
const cylinderMesh new THREE.Mesh(cylinder,cylindermaterial)
scene.add(cylinderMesh)接下来在圆柱体中设置一个聚光灯让聚光灯偏垂直照射汽车模型如下
// 设置聚光灯(让汽车更具有立体金属感)
const spotLight new THREE.SpotLight(#fff,2)
spotLight.angle Math.PI / 8 // 散射角度和水平线的夹角
spotLight.penumbra 0.2 // 横向聚光锥的半影衰减百分比
spotLight.decay 2 // 纵向沿着光照距离的衰减量
spotLight.distance 30
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)为了不让展厅穿帮这里将控制器的缩放以及旋转角度进行一个限制让其只能在展厅中灵活查看而不能跑到展厅外面去
controls.maxDistance 10 // 最大缩放距离
controls.minDistance 1 // 最小缩放距离
controls.minPolarAngle 0 // 最小旋转角度
controls.maxPolarAngle 85 / 360 * 2 * Math.PI // 最大旋转角度设置GUI面板动态控制车身操作
这里我使用three.js库中自带的gui库来动态的改变车身相关操作因为我仅仅是控制车身材质和玻璃材质相关的数据操作这里就线设置一下其相关的材质
// 车身材质
let bodyMaterial new THREE.MeshPhysicalMaterial({color: red,metalness: 1,roughness: 0.5,clearcoat: 1.0,clearcoatRoughness: 0.03
})
// 玻璃材质
let glassMaterial new THREE.MeshPhysicalMaterial({color: #793e3e,metalness: 0.25,roughness: 0,transmission: 1.0 // 透光性
})在glb模型中通过traverse函数遍历场景中的所有对象包括Mesh、Group、Camera、Light等并对这些对象进行相应操作或处理这里的门操作后面会讲解到
loader.load(/public/model/Lamborghini.glb,(gltf){const carModel gltf.scenecarModel.rotation.y Math.PIcarModel.traverse((obj){if(obj.name Object_103 || obj.name Object_64 || obj.name Object_77){// 车身obj.material bodyMaterial}else if(obj.name Object_90){// 玻璃obj.material glassMaterial}else if(obj.name Empty001_16 || obj.name Empty002_20){// 门// doors.push(obj)}else{return true}})scene.add(gltf.scene)
})最后得到的结果如下 接下来通过控制面板来动态的监视汽车模型的车身和玻璃材质
// 设置gui模板控制
// 修改默认面板名称
gui.domElement.parentNode.querySelector(.title).textContent 3D汽车动态操作const bodyChange gui.addFolder(车身材质设置)
bodyChange.close() // 默认关闭状态
bodyChange.addColor(bodyMaterial,color).name(车身颜色).onChange(value{bodyMaterial.color.set(value)
})
bodyChange.add(bodyMaterial,metalness,0,1).name(金属度).onChange(value{bodyMaterial.metalness value
})
bodyChange.add(bodyMaterial,roughness,0,1).name(粗糙度).onChange(value{bodyMaterial.roughness value
})
bodyChange.add(bodyMaterial,clearcoat,0,1).name(清漆强度).onChange(value{bodyMaterial.clearcoat value
})
bodyChange.add(bodyMaterial,clearcoatRoughness,0,1).name(清漆层粗糙度).onChange(value{bodyMaterial.clearcoatRoughness value
})
const glassChange gui.addFolder(玻璃设置)
glassChange.close() // 默认关闭状态
glassChange.addColor(glassMaterial,color).name(玻璃颜色).onChange(value{glassMaterial.color.set(value)
})
glassChange.add(glassMaterial,metalness,0,1).name(金属度).onChange(value{glassMaterial.metalness value
})
glassChange.add(glassMaterial,roughness,0,1).name(粗糙度).onChange(value{glassMaterial.roughness value
})
glassChange.add(glassMaterial,transmission,0,1).name(透光性).onChange(value{glassMaterial.transmission value
})车门操作与车身视角展示
这里依然用GUI控制面板来动态实现开关车门以及车内车外视角动态切换的操作如下
var obj { carRightOpen,carLeftOpen,carRightClose,carLeftClose,carIn,carOut }
// 设置车身动态操作
const doChange gui.addFolder(车身动态操作设置)
doChange.close() // 默认关闭状态
doChange.add(obj, carLeftOpen).name(打开左车门)
doChange.add(obj, carRightOpen).name(打开右车门)
doChange.add(obj, carLeftClose).name(关闭左车门)
doChange.add(obj, carRightClose).name(关闭右车门)
doChange.add(obj, carIn).name(车内视角)
doChange.add(obj, carOut).name(车外视角)每个操作都对应一个函数如下
// 打开左车门
const carLeftOpen () { setAnimationDoor({ x: 0 }, { x: Math.PI / 3 }, doors[1])
}
// 打开右车门
const carRightOpen () { setAnimationDoor({ x: 0 }, { x: Math.PI / 3 }, doors[0])
}
// 关闭左车门
const carLeftClose () { setAnimationDoor({ x: Math.PI / 3 }, { x: 0 }, doors[1])
}
// 关闭右车门
const carRightClose () { setAnimationDoor({ x: Math.PI / 3 }, { x: 0 }, doors[0])
}// 车内视角
const carIn () {setAnimationCamera({ cx: 4.25, cy: 1.4, cz: -4.5, ox: 0, oy: 0.5, oz: 0 }, { cx: -0.27, cy: 0.83, cz: 0.60, ox: 0, oy: 0.5, oz: -3 });
}
// 车外视角
const carOut () {setAnimationCamera({ cx: -0.27, cy: 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 });
}这里使用了补间动画tween.js其github网址为 github.com/tweenjs/twe… 终端安装其第三方插件之后直接引入即可如下这里不再过多介绍该库的使用想学习的可以自行寻找其官方文档学习 接下来借助tween.js库实现补间动画如下
// 设置补间动画
const setAnimationDoor (start, end, mesh) {const tween new TWEEN.Tween(start).to(end, 1000).easing(TWEEN.Easing.Quadratic.Out)tween.onUpdate((that) {mesh.rotation.x that.x})tween.start()
}
const setAnimationCamera (start, end) {const tween new TWEEN.Tween(start).to(end, 3000).easing(TWEEN.Easing.Quadratic.Out)tween.onUpdate((that) {// camera.postition 和 controls.target 一起使用camera.position.set(that.cx, that.cy, that.cz)controls.target.set(that.ox, that.oy, that.oz)})tween.start()
}最终实现的效果如下 点击查看车内视角的话画面如下 设置手动点击打开关闭车门
通过设置监听点击事件函数来动态实现打开关闭车门
// 设置点击打开车门的动画效果
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;var vector new THREE.Vector2(pointer.x, pointer.y)var raycaster new THREE.Raycaster()raycaster.setFromCamera(vector, camera)let intersects raycaster.intersectObjects(scene.children);intersects.forEach((item) {if (item.object.name Object_64 || item.object.name Object_77) {if (!carStatus || carStatus close) {carLeftOpen()carRightOpen()} else {carLeftClose()carRightClose()}}})
}然后给每个车门设置汽车状态如下 设置图片背景
为了让展厅更具有视觉效果接下来设置一个画面背景让其更具有画面感如下
// 创建聚光灯函数
const createSpotlight (color) {const newObj new THREE.SpotLight(color, 2);newObj.castShadow true;newObj.angle Math.PI / 6;;newObj.penumbra 0.2;newObj.decay 2;newObj.distance 50;return newObj;
}// 设置图片背景
const spotLight1 createSpotlight(#ffffff);
const texture new THREE.TextureLoader().load(src/assets/imgs/奥特曼.jpg)
spotLight1.position.set(0, 3, 0);
spotLight1.target.position.set(-10, 3, 10)
spotLight1.map texture
const lightHelper new THREE.SpotLightHelper(spotLight1);
scene.add(spotLight1);最终呈现的效果如下 原文链接 https://juejin.cn/post/7307146429004333094