threejs路径
路徑
引用百度百科的解釋:
路徑通常指存在于多種計算機圖形設計軟件中的以貝塞爾曲線為理論基礎的區域繪制方式。路徑在Canvas、SVG上都有相關定義,一般用來創建形狀。在threejs中,也可以用來創建形狀,除此之外,還可以用作物體運動的軌跡。下面就說說這兩種用法。
在threejs中,Path類代表路徑,Path繼承自CurvePath(曲線路徑),CurvePath繼承自Curve(曲線)。CurvePath和Curve都是抽象類,在threejs文檔中指出,CurvePath用來連接多條曲線(也就是Curve),其實質上就是一個Curve數組。其實,直接用Path類就可以了,對于CurvePath和Curve,無需關心。
另外還有一個ShapePath類,這個類可以將形狀轉成一系列路徑來表示,比如將svg繪制的圖形轉成threejs的路徑。
使用路徑創建形狀
關于使用路徑創建形狀,可以參考【創建平面幾何形狀一文】,其中的Shape類,就是Path類的子類,這里不多說。
使用路徑作為物體運動軌跡
如果我們想要物體沿著某一條曲線運動,有兩種辦法:
1、算出曲線的公式,動態的計算出物體當前時刻的位置
2、創建一條代表該曲線的路徑,然后動態的在該曲線上取點,將其位置賦給物體
一般,路徑類會提供多種創建路徑的方法,所以,第2種方式通常比較好用。
下面就使用threejs提供的Path類創建一條移動軌跡,然后把相機在這條軌跡上移動。開始的開始,先創建一條路徑,如下:
path = new THREE.Path();path.bezierCurveTo(10,100,20,-30,30,19);path.bezierCurveTo(40,-5,50,150,60,-39);path.closePath();接著在render循環中動態的從路徑中取點,設置成相機的位置:
var progress = 0; function render(){requestAnimationFrame(render);progress += 0.003;let point = path.getPointAt(progress);if(point){camera.position.set(point.x,point.y,300);}else{progress = 0;}renderer.render(scene,camera); }上面的progress是比例,范圍從0~1.完整示例請看【完整示例】
將svg形狀轉成路徑
svg是一種矢量圖形格式,同時,javascript也有創建和修改這種圖形格式的接口。各種表示矢量圖形的技術,如Canvas、SVG,本質上是相同或相通的,只不過是實現和接口不一樣,所以,是有轉化的可能的。
在svg中,下面的代碼創建了一條從(0,0)到(100,100)的直線路徑:
<path d="M0 0 L 100 100"/>而在threejs中,使用ShapePath創建一條直線路徑使用:
let path = new ShapePath(); path.moveTo(0,0); path.lineTo(100,100);可見,兩者的形式是相近的,從形式上來看,簡單的轉換難度也不會很大。下面是一個轉換的例子:
function createShapes(){let dataString = getSvgData(); //獲取svg數據let shape = transformToShapePath(dataString); //轉換成ShapePath表示let geometry = new THREE.ShapeGeometry(shape);let material = new THREE.LineBasicMaterial({color:0xff0000});let mesh = new THREE.Line(geometry,material);scene.add(mesh);camera.lookAt(mesh.position); }//獲取svg數據,數據來自w3cschool function getSvgData(){let svgData = "M153 334 C153 334 151 334 151 334 C151 339 153 344 156 344 C164 344 171 339 171 334 C171 322 164 314 156 314 C142 314 131 322 131 334 C131 350 142 364 156 364 C175 364 191 350 191 334 C191 311 175 294 156 294 C131 294 111 311 111 334 C111 361 131 384 156 384 C186 384 211 361 211 334 C211 300 186 274 156 274";return svgData; }//轉換成ShapePath表示 function transformToShapePath(dataString){let path = new THREE.ShapePath();let dataArr = dataString.split(" ");var currIndex = 0;while(currIndex<dataArr.length){let command = dataArr[currIndex][0];switch(command){case 'M' : {let inc = moveParse(currIndex,dataArr,path);currIndex += inc;break;}case 'C' : {let inc = curveParse(currIndex,dataArr,path);currIndex += inc;break;}default:{//出錯處理currIndex++;}}}return path.toShapes()[0]; }/**************下面是各種命令的轉換器****************///moveTo命令轉換器function moveParse(currIndex,dataArr,path){let paramsLength = 2; //需要的參數個數let data = [dataArr[currIndex].substring(1),dataArr[currIndex+1]];toThreejsCoor(data);path.moveTo(data[0],data[1]);return paramsLength;}//Curve命令轉換器function curveParse(currIndex,dataArr,path){let paramsLength = 6; //需要的參數個數let data = [ dataArr[currIndex].substring(1),dataArr[currIndex+1],dataArr[currIndex+2],dataArr[currIndex+3],dataArr[currIndex+4],dataArr[currIndex+5]];toThreejsCoor(data);path.bezierCurveTo(data[0],data[1],data[2],data[3],data[4],data[5]);return paramsLength;}//屏幕坐標轉threejs坐標function toThreejsCoor(data){for(let i = 0 ; i < data.length; i += 2){data[i] = data[i] - window.innerWidth/2;data[i+1] = window.innerHeight/2 - data[i+1];}}上面的代碼做了下面這幾件事:
- 從svg中提取圖形的定義數據,比如<path>標簽的d屬性
- 將所提取數據中的坐標轉換成threejs坐標
- 分析所提取的數據里的操作,用ShapePath執行這些操作
- 調用ShapePath類的toShapes()方法,獲得一個Path對象數組
- 用這個Path數組中的對象,創建threejs圖形。
這也是將svg轉成Path的幾個基本步奏。經過轉換之后,屏幕上會顯示出如下圖形:
完整效果,請戳【完整示例】
總結
- 上一篇: 微信小程序获取tabbar的高度_微信小
- 下一篇: [Head First Java] -