HTML5 網絡拓撲圖性能優化


HTML5 中的 Canvas 對文本的渲染(fillText,strokeText)性能都不太好,比如設置字體(font)、文本旋轉(rotation),如果繪制較多的文本時,一些交互操作會手動很大的影響,操作起來沒那么順暢,體驗將會極其差,這不是我們想要的結果,再進一步和圖片的繪制進行比較比較,你會發現,繪制圖片和繪制文本在性能上不是一個等級的,在性能上繪制圖片會好太多。

我們今天就來談談 HT for Web 性能相關的問題。在 HT 中,有很多地方可以設置文本,每個節點上面都可以設置兩個 label 和兩個 note 文本,如果全開啟的話,繪制一個節點就要附帶繪制 4 個文本,假如說繪制 文本的性能消耗是繪制圖片性能消耗的 3 倍的話,附帶繪制 4 個文本,就想當與多出 12 倍的性能消耗,這節點以多的話,可想而知,不管是哪個引擎都不可能 hold 得住這樣的性能消耗。

既然繪制文本的性能消耗無法避免,那么我們要如何提高系統的整體性能呢?換個思路,繪制文本會有高性能消耗,導致操作上面的延遲和卡頓,那么我是不是可以在操作時不繪制文本呢,將文本繪制所消耗的性能節省下來,用在其他的性能消耗上,這樣是不是就可以解決操作延遲和卡頓的問題呢?

我們不妨來試試,在 GraphView 中添加若干個 node、edge、group 等節點,並且每個節點上都顯示文本(包括線條,上圖所示),看看拓撲的縮放效果怎么樣。沒次縮放都要等上兩三秒,性能實在是差得不行,這樣的應用肯定是不合格的。

我們來看看具體的 Demo,鏈接:http://www.hightopo.com/demo/labelVisible/visible.html。接下來解析下具體代碼的實現。

var init = function() {
    window.matchMedia('screen and (min-resolution: 2dppx)').
        addListener(function() {
            ht.Default.setDevicePixelRatio();
        });

    var g2d = new ht.graph.GraphView(),
        dm = g2d.dm();
    g2d.addToDOM();
    g2d.getLabel = function(data) {
        if (data.s('label'))
            return data.s('label');
        if (data instanceof ht.Edge)
            return 'from:' + data.getSourceAgent().toString() + 
                ' to:' + data.getTargetAgent().toString();
        return data.toString();
    };

    createNodes(dm);

    var autoLayout = new ht.layout.AutoLayout(g2d);
    autoLayout.setAnimate(true);
    autoLayout.layout('symmetric', function() {
        g2d.fitContent(true);
    });

    createFormPane(g2d, autoLayout);
};

上面的代碼是頁面初始化代碼,首先先監聽 media 的值變化,防止在不同的 devicePixelRatio 屏幕中切換 而導致頁面不清晰,ht.Default.setDevicePixelRatio() 方法會更新 HT 系統中存放 devicePixelRatio 的變量,然后刷新頁面上所有的 HT 組件,這樣就可以保證頁面一定不會不清晰。

接着是常見網絡拓撲圖 GraphView 組件,並將其添加到 DOM 中,重載 GraphView 的 getLabel 方法設置圖元的文本,讓每個節點都有文本。

接下來調用 createNodes 方法創建所有的節點,創建完代碼后,創建一個 AutoLayout 來自動布局所有節點,自動布局為開發人員節省手動布局的時間,在效率上大大提升,在布局完后,讓 GraphView 中的節點自適應屏幕,讓所有節點都顯示在當前頁面中。

最后創建一個 FormPane 放在右上角,用於存放幾個控制按鈕及幾個 ComboBox 選擇項,可以讓 GraphView 運行在不同的布局模式下,同時這些功能也可以用來檢測頁面性能,在布局的過程中是否流暢,具體的代碼可以通過瀏覽器的 Sources 查看。

文本始終顯示的話,在性能上還是不行的,就如上面所說的,是不合格的。那么我么該如何優化,讓性能有質的提升呢?

在文章的開頭有提到,我們可以采用在操作交互的過程中不繪制文本,來提升性能,讓頁面的呈現更加流暢。那么該怎么實現才能讓操作交互過程中不繪制文本呢?具體 Demo 鏈接:http://www.hightopo.com/demo/labelVisible/invisible.html。看碼:

var state = {};
g2d.isLabelVisible = function(data) {
    return !state.zooming && !state.panning && !state.autoLayout;
};
g2d.onAutoLayoutEnded = function() {
    state.autoLayout = false;
};
g2d.onZoomEnded = function() {
    state.zooming = false;
};
var timer = null;
g2d.mp(function(e) {
    if (e.property === 'zoom') {
        state.zooming = true;
        if (timer)
            clearTimeout(timer);
        timer = setTimeout(function() {
            timer = null;
            state.zooming = false;
            g2d.redraw();
        }, 100);
    }
});
g2d.mi(function(e) {
    if (e.kind === 'beginPan')
        state.panning = true;
    if (e.kind === 'endPan') {
        state.panning = false;
        g2d.redraw();
    }
});

首先 GraphView 提供了 isLabelVisible  的方法,讓用戶重載自定義文本的顯示與否,state 變量是用來標記當前的操作狀態,zooming 代表當前的 GraphView正在縮放,panning 代表當前的 GraphView 正在移動整個場景,autoLayout 代表正在做自動布局操作。

GraphView 的 mp(addPropertyChangeListener)方法是監聽 GraphView的屬性變化,當監聽到 zoom 屬性變化的時候,將 zooming 狀態設置為 true,如果在 zoom 的過程中沒有啟動動畫的話,就不會觸發 onZoomEnded 回調,所以需要自己添加計時器,過段時間將 zooming 狀態改掉,並且重新繪制下 GraphView。

GraphView 的 mi(addInteractorListener)方法是監聽用戶對 GraphView 的操作動作,在監聽到 beginPan 時將 panning 狀態設置為 true ,在監聽到 endPan 是將 panning 狀態設置為 false,並重繪 GraphView。

在 FormPane 中的一些操作會對 GraphView 中的節點進行自動布局,因此在 FormPane 中會設置 autoLayout 狀態,由於代碼比較多,我在這邊就貼代碼了。我們來看看,加上上面的代碼后,對 GraphView 操作后的效果圖:

上圖是在縮放 GraphView 時的效果,可以發現所有的文本都不見了,用戶操作起來也不會延遲和卡頓了現象,這樣用戶操作交互的性能問題也就解決了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM