基於HTML5 WebGL實現 json工控風機葉輪旋轉

圖撲軟體發表於2017-10-26

突然有個想法,如果能把一些用到不同的知識點放到同一個介面上,並且放到一個盒子裡,這樣我如果要看什麼東西就可以很直接顯示出來,而且這個盒子一定要能開啟。我用HT實現了我的想法,程式碼一百多行,這麼少的程式碼能實現這種效果我覺得還是牛的。

demo地址: http://www.hightopo.com/demo/Wall3D/index.html

先來看看效果圖:


 

這個例子最基礎的就是最外層的盒子了,所以我們先來看看如何實現它:

var box = new ht.CSGBox();
dataModel.add(box);

 用HT可以很輕易地實現這個盒子,在HT中封裝了很多基礎圖元型別,我們經常用到的ht.Node也是其中一個,這樣我們可以不用反覆地寫相同的程式碼來完成基礎的實現。

 

這個例子中用的封裝好的基礎圖元是ht.CSGBox,一個盒子模型,可以參考HT for Web 建模手冊,我們在手冊中可以看到,在CSGBox中我們只能操作這個盒子的各個面,如果你想要自己設定一些特殊的功能,只需要操作ht.Style(HT for Web 風格手冊)即可。

我想你們都注意到了盒子上有模型化的水泵,上面有扇葉在旋轉,那麼這個水泵是怎麼生成的呢?我用我們的2d編輯器寫了一個水泵模型通過graphView.serialization(datamodel)將模型序列化成json格式的檔案,然後在這邊引用的時候我再呼叫graphView.deserialize(json)來將json檔案匯出成視覺化的2d模型並設定animation動畫,再立即重新整理到這個水泵,否則就算設定了動畫,水泵上的扇葉旋轉也不會生效。

ht.Default.xhrLoad('displays/demo/pump.json', function(text){
    const json = ht.Default.parse(text);
    pumpDM.deserialize(json);
    var currentRotation = 0;
    var lastTime = new Date().getTime();

    setInterval(function(){
        var time = new Date().getTime();
        var deltaTime = time - lastTime;
        currentRotation += deltaTime * Math.PI / 180 * 0.3;
        lastTime = time;

        pumpDM.getDataByTag('fan1').setRotation(currentRotation);
        pumpDM.getDataByTag('fan2').setRotation(currentRotation);
        box.iv();
        // g3d.iv();這邊也可以重新整理g3d,但是區域性重新整理更省
        pumpGV.validateImpl();
    }, 10);
}, 10);

 這個時候我不能把水泵的graphView和g3d都加到底層div上,並且我的意圖是把水泵的graphView加到g3d中的CSGBox中的一面上,所以為了讓水泵顯示出來 必須設定水泵所在的graphView的寬高,而這個寬高必須比我json畫出來的圖佔的面積要大,不然顯示不完整。如果想看這個寬高對顯示的影響,可以自己改改看來玩玩。

pumpGV.getWidth = function() { return 600;}
pumpGV.getHeight = function(){ return 600;}
pumpGV.getCanvas().dynamic = true;//設定這個是為了讓canvas能動態顯示

 這邊還要特別說明一個函式getDataByTag(tagName)這個函式是獲取標識號,在HT中tag屬性是唯一標識,雖然HT中也有id,但是id是HT中Data型別物件構造時內部自動被賦予的一個id屬性,可以通過data.getId()和data.setId(id)獲取和設定,Data物件新增到DataModel之後不允許修改id值,可以通過dataModel.getDataById(id)快速查詢Data物件。

一般我們建議id屬性由HT自動分配,使用者業務意義的唯一標示可存在於tag屬性上,通過data.setTag(tag)函式允許任意動態改變tag值,通過dataModel.getDataByTag(tag)可查詢到對應的Data物件,並支援通過dataModel.removeDataByTag(tag)刪除Data物件。

你可能會好奇在程式碼中我們並沒有提到“fan1”這個tag標識,這個標識是在水泵的json中設定的,關於扇葉的一個標識,我們獲取到扇葉,然後設定其旋轉。

echarts圖表的顯示也是很基礎的,但是我們會發現,在將echarts圖表新增進graphView中它的動畫效果會不顯示,所以我們首先要將這個echarts圖表所在的圖表的dynamic設定為true,即將其設定為動態:

function charts(option){
    var info = {
        canvas: document.createElement('canvas')
    };
    info.canvas.dynamic = true;//設定info.canvas為動態
    info.chart = echarts.init(info.canvas);
    info.chart.setOption(option);
    return info.canvas;
}

最後,只需要將這兩個回傳的canvas傳入ht.Default.setImage中即可:

ht.Default.setImage('echart', charts(option));
ht.Default.setImage('pump', pumpGV.getCanvas());

 ht.Default.drawImage函式生成新的圖實際上就是在canvas上畫圖,所以我們只要把我們已經畫好的canvas傳到ht.Default.setImage就可以生成圖片了。

相關文章