開講以前,先上個案例
演示地址: 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