今天正值中国的传统节日——七夕节,在此祝所有有情人终成眷属。这个节日很美好,但是对于很多男士来说是一个煎熬的日子,毕竟礼物买不好轻则跪搓衣板,重则口袋空空,有同样困扰的我也不知道如何处理,最终搞了束玫瑰花给媳妇(如下),但是最终还是没有摆脱跪搓衣板这一酷刑(被人家嫌弃太程序员了,,Ծ‸Ծ,,)。
一、基础实现
Three.js将WebGL底层的图形接口进行封装,这样就无需掌握复杂的图形学和复杂的数学知识,提高开发效率,本次就漂亮的玫瑰就是利用Three.js实现整。为了利用Three.js将模型展示在浏览器中,需要结合渲染器、场景、相机、模型和光照等。Three.js创建流程如图所示,其创建流程包括以下几个步骤:
为了方便看懂下面的代码,可以先下载本节所对应的代码包 (提取码6666)
1.1 获取Canvas节点
获取DOM树中的Canvas节点,该节点是图形绘制的容器,是最终展示三维模型的载体。
<div> <canvas id="rose" width="500px" height="500px"></canvas> </div>
1.2 设置渲染器
渲染器决定了场景中内容渲染的最终结果,通过设置渲染器,为后续的渲染工作起到了准备作用。
// 设置渲染器(为WebGLRenderer渲染器) this.renderer = new THREE.WebGLRenderer({ canvas, antialias: true // 抗锯齿 }); // 设置尺寸 this.renderer.setSize(canvasWidth, canvasHeight); // 设置背景颜色 this.renderer.setClearColor(0x6495ED);
1.3 创建场景
场景就是一个很大的三维空间,类似于一个容器,是用于保存相机、光源和模型等对象的场所。
// 设置场景 this.scene = new THREE.Scene();
1.4 往场景内添加元素
将相机、模型、光照添加到场景中。相机是为了将三维空间中的模型映射到二维平面上,模型是最终希望在页面上呈现的物体,光照是为了增加更好的视觉体验,为整个场景增添真实感。
// 设置相机 this.camera = new THREE.PerspectiveCamera(60 ,canvasWidth / canvasHeight, 1,10000); this.camera.position.set(800, 800, 800); this.camera.lookAt(new THREE.Vector3(0, 0, 0)); this.scene.add(this.camera); // 添加光源 const pointLight = new THREE.PointLight(0xffffff, 1, 0); pointLight.position.set(1000, 1000, 1000); this.scene.add(pointLight); const ambientLight = new THREE.AmbientLight(0x404040); this.scene.add(ambientLight); // 添加模型 models.forEach(model =>{ const {obj, position} = model; obj.position.set(...position); this.group.add(obj); this.scene.add(this.group); });
注意:模型部分是通过加载器(OBJLoader+MTLLoader)加载的obj+mtl格式的文件,加载代码如下所示:
loadModule(model) { const {objUrl, mtlUrl} = model; let mtlLoader = new THREE.MTLLoader; let objLoader = new THREE.OBJLoader; return new Promise((resolve, reject) => { mtlLoader.load(mtlUrl, material =>{ objLoader.setMaterials(material); objLoader.load(objUrl, obj =>{ obj.traverse(child =>{ if (child instanceof THREE.Mesh) { child.material.side = THREE.DoubleSide; } }); model.obj = obj; resolve(model); }); }); }); }
1.5 渲染模型
通过调用渲染器的渲染函数将模型渲染到页面上进行展示。
this.renderer.render(this.scene, this.camera);
二、进阶
通过上述五个步骤就可以实现一个静态部分的玫瑰花了,但是并不能仅仅如此就完事了,还是要有一定精益求精的精神的,下面在原有基础上我们旋转渲染动效和轨道控制能力。
2.1 旋转动效
所谓旋转动效其实就是上面看到按照y坐标旋转的效果,其是怎么实现的呢?其实归结起来可以分为两个步骤:
- 利用requsetAnimationFrame进行循环调用渲染动作;
- 每次渲染时修改几何模型的y轴方向的角度。
Animate(); function Animate() { window.requestAnimationFrame(Animate); this.group.rotation.y += 0.01; this.renderer.render(self.scene, self.camera); }
2.2 轨道控制能力
轨道控制使用了OrbitControls.js库,使摄像机可以围绕目标旋转,实现几何体的滚动、缩放、拖动等能力。
function useOribitControls(camera, renderDom) { const controls = new THREE.OrbitControls(camera, renderDom); controls.enableRotate = true; controls.rotateSpeed = 0.8; controls.enableZoom = true; controls.zoomSpeed = 1.2; controls.enableDamping = true; return controls; }
然后通过在requestAnimationFrame总更新其控制实例即可
Animate(); function Animate() { window.requestAnimationFrame(Animate); this.controls.update(); this.renderer.render(self.scene, self.camera); }