开讲以前,先上个案例
演示地址: http://www.yxyy.name/example/...
下载地址:https://github.com/buglas/exa... > supPath.htmlhtml
1.路径跟随必备对象:移动物体和路径git
2.须要考虑的状况:github
旋转方向不受路径约束canvas
旋转方向受路径约束less
3.物体的旋转方向若要受路径约束,有两种实现方式:动画
硬旋转:物体旋转角度和其所在线段的方向匹配(假设路径是由线段组成的)。spa
软旋转:物体在路径的转折处,圆滑过分。code
4.实现软旋转的思路有两种:htm
5.预先圆滑中,物体跟随的路径是已经被修改过的,因此它的移动轨迹也会和最初的路径不吻合。对象
6.实时圆滑能够将物体的旋转属性和位置属性分离的,如图
此示例须要three.js 基础,对于three.js 环节,我只作简单概述。
1.搭建场景:
//获取html 里的canvas const canvas = document.querySelector('#c'); const width = canvas.clientWidth; const height = canvas.clientHeight; //渲染器 const renderer = new THREE.WebGLRenderer({canvas}); renderer.setSize(width, height, false); //相机 const fov = 45; const aspect = width / height; const near = 0.01; const far = 10; const camera = new THREE.PerspectiveCamera(fov, aspect, near, far); camera.position.set(0, 2, 0); camera.updateProjectionMatrix(); //场景 const scene = new THREE.Scene();
2.绘制路径
let curve; let curveObject; { const points = [ [0.5,0,0.5], [-0.5,0,0.5], [-0.5,0,-0.5], ]; curve = new THREE.CatmullRomCurve3( points.map((p, ndx) => { return (new THREE.Vector3()).set(...p); }), true, 'catmullrom', 0.01 ); { const points = curve.getPoints(6); const geometry = new THREE.BufferGeometry().setFromPoints(points); const material = new THREE.LineBasicMaterial({color: 0xff0000}); curveObject = new THREE.Line(geometry, material); scene.add(curveObject); }; }
3.创建运动物体。
先用一个简单的box 表示汽车。飞机的话,还得导入模型进来。先讲重点。
let car; { const geometry =new THREE.BoxBufferGeometry(.1,.1,.2); const material = new THREE.MeshBasicMaterial( {color: 0xcccccc} ); car = new THREE.Mesh( geometry, material ); scene.add(car); }
4.路径跟随动画
//汽车位置 const carPosition = new THREE.Vector3(); //汽车目标点 const carTarget = new THREE.Vector3(); function render(time) { //将递增的时间转化为距离 let distance = time*0.0002; // convert to seconds { //目标点到目标的距离 const targetOffset = 0.1; //从曲线上获取汽车点位。getPointAt 详情查手册。 curve.getPointAt(distance % 1, carPosition); //从曲线上获取汽车目标点位 curve.getPointAt((distance + targetOffset) % 1, carTarget); //汽车定位 car.position.copy(carPosition); //实现软旋转 car.lookAt(carTarget); //圆滑位置 //car.position.lerpVectors(carPosition, carTarget, 0.5); } renderer.render(scene, camera); requestAnimationFrame(render); } requestAnimationFrame(render);
注:{} 包裹代码的写法是跟let const 命令的块级做用域有关,如此能够避免变量污染上层对象的命名空间。
实例效果演示: http://www.yxyy.name/funk/路...
实例源文件:https://github.com/buglas/fun... > 路径跟随.html