拓撲圖線條流動效果

jopen 10年前發布 | 9K 次閱讀 拓撲圖

        圖論中邊是重要元素,它連接各個頂點構成拓撲圖,有向圖中,邊具有方向性,在畫布中表現為箭頭,在實際應用中,邊可以代表鏈路,鏈路 上不只是有方向,還有流量,信號種類等信息,光用箭頭表現力就不夠了,可增加線條線型,以及流動效果來體現,這里介紹 Qunee 1.6 中線條流動效果的實現 拓撲圖線條流動效果

        虛線流動效果

        虛線流動效果在 連線示例中有演示,使用虛線偏移量樣式,不斷增大,實現線條的流動

        虛線流動代碼

var offset = ;var index = ;var timer = setInterval (function (){
    offset += -1;//    edge2.setStyle (Q.Styles.EDGE_LINE_DASH_OFFSET, offset);     
    edge1.setStyle (Q.Styles.EDGE_LINE_DASH_OFFSET, offset);
    index++;
    index = index%20;
    edge2.setStyle (Q.Styles.ARROW_TO_OFFSET, -0.3 -0.02 * (20 - index));
    edge1.setStyle (Q.Styles.ARROW_FROM_OFFSET, {x: 0.3 + 0.02 * (20 - index), y: -10});
}, 150);

        運行效果

拓撲圖線條流動效果

 

        定制流動效果

        對于更高級的流動需求,需要定制來實現,原理是在線條上掛載一個小圖標,讓這個圖標沿線移動,從而形成動畫效果

        實現代碼

        下面的代碼實現在線條上移動小圖標

var line = graph.createShapeNode ("Line");
line.moveTo (-100, );
line.lineTo (200, );
line.curveTo (300, , 300, 100, 200, 100);
line.lineTo (, 100);
line.closePath ();
line.setStyle (Q.Styles.SHAPE_STROKE_STYLE, "#2898E0");
line.setStyle (Q.Styles.SHAPE_LINE_DASH, [8, 5, 0.1, 6]);
line.setStyle (Q.Styles.SHAPE_STROKE, 3);
line.setStyle (Q.Styles.LINE_CAP, "round");
line.setStyle (Q.Styles.SHAPE_OUTLINE_STYLE, "#fcfb9b");var ui = new Q.ImageUI ("images/flow.png");
ui.position = {x: , y: };
ui.size = {width: 20};
ui.renderColor = "#F00";
line.addUI (ui);

setTimeout (function A (){
    var x = ui.position.x + 20;
    ui.position = {x: x % (ui.parent.length || 1), y: };
    line.invalidate ();
    setTimeout (A, 300);
}, 100)

        運行效果 

拓撲圖線條流動效果

        進一步封裝

        上面的實現太隨意,實際使用不太方便,可以進一步封裝成專門用于流動支持的類,這樣可以通過一個定時器實現所有的流動支持,我們創建一個 FlowingSupport 的類,詳細代碼如下

        FlowingSupport 類代碼

 function FlowingSupport (graph) {
    this.flowMap = {};
    this.graph = graph;
}
FlowingSupport.prototype = {
    flowMap: null,
    length: ,
    gap: 40,
    graph: null,
    addFlowing: function (edgeOrLine, count, byPercent) {
        var flowList = this.flowMap[edgeOrLine.id];
        if(!flowList){
            flowList = this.flowMap[edgeOrLine.id] = [];
            this.length++;
        }
        count = count || 1;
        while(--count >= ){
            var ui = new Q.ImageUI ("network/images/flow.png");
            ui.position = {x: , y: };
            ui.size = {width: 20};
            ui.renderColor = "#F00";
            flowList.push (ui);
            flowList.byPercent = byPercent;
            edgeOrLine.addUI (ui);
        }
    },
    removeFlowing: function (id){
        var flowList = this.flowMap[id];
        if(!flowList){
            return;
        }
        var edgeOrLine = this.graph.getElement (id);
        if(edgeOrLine){
            flowList.forEach (function (ui){
                edgeOrLine.removeUI (ui);
            })
        }
        this._doRemove (id);
    },
    _doRemove: function (id){
        delete this.flowMap[id];
        this.length--;
    },
    timer: null,
    perStep: 10,
    stop: function (){
        clearTimeout (this.timer);
    },
    start: function (){
        if(this.timer){
            clearTimeout (this.timer);
        }
        var offset = ;
        var scope = this;
        scope.timer = setTimeout (function A () {
            if (!scope.length) {
                scope.timer = setTimeout (A, 2000);
                offset = ;
                return;
            }
            offset += 1;
            for(var id in scope.flowMap){
                var ui = scope.graph.getUI (id);
                if(!ui){
                    scope._doRemove (id);
                    continue;
                }
                var lineLength = ui.length;
                if(!lineLength){
                    continue;
                }
                var flowList = scope.flowMap[id];
                if(flowList.byPercent){
                    //按百分比,0 - 1 跑完整條線,線長度不同,速度也不同,跑完一圈的時間相同 var x = offset * 2;
                    var gap = 15;
                    scope.flowMap[id].forEach (function (ui){
                        ui.position = {x: (x % 100) / 100, y: };
                        x += gap;
                    });
                }else{
                    //按固定距離移動,速度相同,線條越長跑完一圈的時間越長 var x = offset * scope.perStep;
                    scope.flowMap[id].forEach (function (ui){
                        ui.position = {x: x % lineLength, y: };
                        x += scope.gap;
                    });
                }
                scope.graph.invalidateUI (ui);

                //dashed line var data = ui.data;
                if(data instanceof Q.Edge){
                    if(data.getStyle (Q.Styles.EDGE_LINE_DASH)){
                        data.setStyle (Q.Styles.EDGE_LINE_DASH_OFFSET, -offset);
                    }
                }else if(data instanceof Q.ShapeNode){
                    if(data.getStyle (Q.Styles.SHAPE_LINE_DASH)) {
                        data.setStyle (Q.Styles.SHAPE_LINE_DASH_OFFSET, -offset);
                    }
                }
            }
            scope.timer = setTimeout (A, 200);
        }, 200);
    }
}

        使用如下

        這里的第二個參數為圖標數量,第三個參數為是否按百分比流動,如果按百分比流動,每次移動的距離為線條長度的百分之二,這意味著不同長度的線條流動一圈,花費的時間相同

 var flowingSupport = new FlowingSupport (graph);
flowingSupport.addFlowing (edge, 3);
flowingSupport.addFlowing (edge2, 1);
flowingSupport.addFlowing (line, 1, true);
flowingSupport.addFlowing (line2, 2, true);

graph.callLater (function (){
    flowingSupport.start ();
})

        運行效果

拓撲圖線條流動效果

        在線演示

        http://demo.qunee.com/#Flowing%20Demo

                    <span id="shareA4" class="fl">                            
                        </span> 

</div>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!