如今,3D模型已經用於各類不一樣的領域。在醫療行業使用它們製做器官的精確模型;電影行業將它們用於活動的人物、物體以及現實電影;視頻遊戲產業將它們做爲計算機與視頻遊戲中的資源;在科學領域將它們做爲化合物的精確模型;建築業將它們用來展現提議的建築物或者風景表現;工程界將它們用於設計新設備、交通工具、結構以及其它應用領域;在最近幾十年,地球科學領域開始構建三維地質模型,並且3D模型常常作成動畫,例如,在故事片電影以及計算機與視頻遊戲中大量地應用三維模型。它們能夠在三維建模工具中使用或者單獨使用。爲了容易造成動畫,一般在模型中加入一些額外的數據,例如,一些人類或者動物的三維模型中有完整的骨骼系統,這樣運動時看起來會更加真實,而且能夠經過關節與骨骼控制運動。html
這些種種都讓咱們前端開發者以爲若是咱們能夠不用學習unity3d或者其餘遊戲開發工具就能實現3D效果,並且可以精準的靠代碼來控制移動或者方向就行了。。。因而我利用HT For Web中的3D組件來實現了一個小例子,用了HT中3D組件的大部分功能,作這個例子就是想把3D組件好好的掌握,儘可能放進一個例子中,到時候別人有須要就能夠參考了,可是由於以前歷來沒有實現過3D的效果,再加上如今手冊沒有很完整,因此這個例子對我來講仍是有點難度的。前端
本例位置:http://www.hightopo.com/demo/...
先來看看總體實現的效果圖:
用HT for Web,現有的3d模板建立三層底板不是問題,問題是要如何將圖中第一層的「電腦」和「機櫃組件」放上去?我是在網上down下來的obj格式的文件,而後我利用HT中的ht.Default.loadObj(objUrl, mtlUrl, params)函數將模型加載進去,其中的params部分能夠參考http://www.hightopo.com/guide...,代碼以下:算法
ht.Default.loadObj('obj/機櫃組件1.obj', 'obj/機櫃組件1.mtl', { cube: true, center: true, shape3d: 'box', finishFunc: function(modelMap, array, rawS3){ window.rawS3 = rawS3; if(modelMap){ device2 = createNode('box', floor1); device2.p3([x1-120, y1+13, z1+60]); device2.s3(rawS3); createEdge(device1, device2); device3 = createNode('box', floor1); device3.s3(rawS3); device3.p3([x1+120, y1+13, z1+60]); createEdge(device1, device3); } } });
「電腦」上方有個紅色的立體能旋轉的「警告」,是依靠ht.Default.setShape3dModel函數(HT for Web 建模手冊)註冊的一個3d模型,在ht中,封裝好的建模函數有不少,比較基礎的就是球體,圓柱,立方體等等,這邊我用的是構造環形的方法createRingModel來生成「警告」最外面的環,感嘆號的上部分就是用的createSmoothSphereModel構造的球體,感嘆號的下部分就是用createSmoothCylinderModel來構造的圓柱。我一開始直接使用了3d模型中封裝好的函數,致使後來根本不知道函數中使用的參數是作什麼用的,並且也不明白3d模型是怎麼構成的,而後本身又從新看了前面的「模型基礎」,才知道原來3d模型採用的一個面,最基礎的是三角面,以後複雜的面也是由多個三角面來造成的,而後繞着一根特定的軸旋轉以後造成的,固然,這個軸是你來決定的,不一樣的軸能夠生成不一樣的形狀,對於顏色等風格方面的設置能夠參考HT for Web 風格手冊。至於如何讓這個3d模型旋轉起來,ht中封裝了addScheduleTask(Task)方法,我在第三層Task中調用了ht封裝的一個旋轉函數setRotation來設置旋轉的順序和方向,而且指定了旋轉的對象。如下是自定義「警告」的3d模型的方法(注意:由於本例的模型是自定義組合的,若是要設置總體模型的顏色要用「all.blend」style屬性):json
var ringModel = ht.Default.createRingModel([8, 1, 10, 1, 10, -1, 8, -1, 8, 1], null, null, false, false, 100); var sphereModel = ht.Default.createSmoothSphereModel(8, 8, 0, Math.PI*2, 0, Math.PI, 2); var cylinderModel = ht.Default.createSmoothCylinderModel(8, true, true, 1, 2, 0, Math.PI*2, 8); var arr = [ { r3: [Math.PI/2, 0, 0], color: 'red' },{ shape3d: sphereModel, t3: [0, 4, 0], color: 'red' },{ shape3d: cylinderModel, t3: [0, -3, 0], color: 'red' } ]; ht.Default.setShape3dModel('alarm', { shape3d: arr });
要實現3D界面上展示2d圖片,只要按照日常的路走就行,由於ht中的Graph3dView和其餘的組件的根部都是div,在div上生成圖片用的就是原生js,new Image(),再將image的src和大小賦值,而且加到3d面板上就好了,注意這裏是加到3d的底層div上,要用g3d.getView().appendChild來添加,咱們還能夠看到管線上有虛線流動的痕跡,這是經過不斷改變「shape3d.uv.offset」參數實現管道流動的特殊效果,詳情請參考HT for Web 形狀手冊。app
想讓2d圖片在3d管線上移動則是使用g3d.toViewPosition(position)來獲取3d模型的二維座標,這個函數中的參數就是三維模型的3d座標,咱們能夠直接將polyline管線上的點傳入toViewPosition函數中,這邊獲取管線上的點在ht中已經封裝好三個函數getLineCacheInfo、getLineLength、getLineOffset,這樣就能夠直接獲取到二維座標,而後將img的座標設置上去便可,如下是img圖片在管道上移動的代碼:ide
var delta = 10; params = { frames: Infinity, interval: 50, action: function(v, t){ var length = (polyline.a('total') || 0) % polyline.a('length') + delta; var cache = ht.Default.getLineCacheInfo(polyline.getPoints(), polyline.getSegments()); var lineLength = ht.Default.getLineLength(cache); var offset = ht.Default.getLineOffset(cache, length); arr = [offset.point.x, offset.point.y, offset.point.z]; var position = g3d.toViewPosition(arr); img.style.left = (position.x - 5) + 'px'; img.style.top = (position.y - 5) + 'px'; polyline.a('total', length); } }; anim = ht.Default.startAnim(params);
能夠看到圖中第二層中的立方體上有「SDH」的字樣,我是經過設置shape3d.top.img: imgURL來實現的,這邊的imgURL能夠是圖片的相對路徑,也能夠是ht中用ht.Default.setImage聲明的img的名稱,還能夠是json格式構造的圖片。在ht中,2D文字顯如今3D上,則字體周圍會出現「鋸齒」,這個時候只要設置「label.transparent: true」便可。函數
咱們還能夠看到第二層上有兩個特殊的多邊形「平行四邊形」和「梯形」,由於以前有客戶說不知道如何使用createExtrusionModel這個模型函數(HT for Web 建模手冊),我索性就寫了一下,平行四邊形是靠createParallelogramModel模型函數,這個函數比較簡單,createExtrusionModel(array, segments, top, bottom, resolution, repeatUVLength, tall, elevation),array是你要造成的圖形的座標點,這邊只是針對於xz軸上畫的平面圖形,segments指的是如何鏈接這幾個座標點,可參考HT for Web 形狀手冊,top和bottom就是讓你選擇是否有頂部或者底部,resolution微分段數,咱們描繪一段曲線的時候可能只要確認幾個個別的點而後在每兩個點之間的連線上把它分紅多個段,這樣這條線段就會變得平滑,ht爲了用戶可以輕鬆操做這些線段,就封裝了這一個參數,repeatUVLength默認爲空,設置值後頂部和底部的貼圖將根據制定長度值進行重複,tall模型的高度,默認爲5,elevation模型中心的y軸位置,默認值爲0,設置這個值可使xz上的平面繞着y軸旋轉。工具
底層的一個環形的效果是經過一個算法來實現的,環形得確認這個環形上有多少個元素,而後算每兩個之間的角度,在經過sin、cos來計算每個元素的位置,得出了以下代碼:學習
names = ['設備2', '設備3', '設備4', '設備5', '設備6', '設備7', '設備8', '設備9']; names.forEach(function(name, index) { x = 400, y = 200, angle = 45, r = 120; x = x3 + Math.sin((2 * Math.PI / 360) * angle * index) * r; y = z3 + Math.cos((2 * Math.PI / 360) * angle * index) * r; device = createRect([x, y3 + 15, y], [w * 0.1, 15, h * 0.1], '', '', floor3); createEdge(device5, device); });