程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Web Chart入門(4) 圖形布局-Layout 之js設計實現

Web Chart入門(4) 圖形布局-Layout 之js設計實現

編輯:關於JAVA

前言

定位browser 的 chart,   VML,SVG, HTML5 Canvas使用的方式各不一樣。

如果使用現有的js  library (各種實現js 圖表的library匯總與比較) , 調用的API方式也肯定不同。

舉個例子: draw2d 使用addFigure 和 setPosition 都可以設置圖的位置。

混在特定技術或是特定library 裡去layout , 很明顯不是一個明智之舉。

切分開來, layout 的功能對於任何的圖形繪制都適用。就是本章所討論的了。

實現思想

其實實現思想很簡單,維護一個JS 的object(Graph)。 在這個Object 裡記錄節點,邊的信息;

節點包含有如下信息:

-- 表示符

-- 橫坐標

-- 縱坐標

shape -- 繪制的圖

這樣的話, 在繪制一個圖節點之前, 先要在這個Graph 維護這個圖節點的一些信息。

Graph 示例

var Graph = function() {  
    this.nodeSet = {};  
    this.nodes = [];  
    this.edges = [];  
    this.adjacency = {};  
      
    this.nextNodeId = 0;  
    this.nextEdgeId = 0;  
    this.eventListeners = [];  
};  
      
var Node = function(id, data) {  
    this.id = id;  
    this.data = typeof(data) !== 'undefined' ? data : {};  
};  
      
var Edge = function(id, source, target, data) {  
    this.id = id;  
    this.source = source;  
    this.target = target;  
    this.data = typeof(data) !== 'undefined' ? data : {};  
};  
      
Graph.prototype.addNode = function(node) {  
    if (typeof(this.nodeSet[node.id]) === 'undefined') {  
        this.nodes.push(node);  
    }  
      
    this.nodeSet[node.id] = node;  
      
    this.notify();  
    return node;  
};  
      
Graph.prototype.addEdge = function(edge) {  
    var exists = false;  
    this.edges.forEach(function(e) {  
        if (edge.id === e.id) { exists = true; }  
    });  
      
    if (!exists) {  
        this.edges.push(edge);  
    }  
      
    if (typeof(this.adjacency[edge.source.id]) === 'undefined') {  
        this.adjacency[edge.source.id] = {};  
    }  
    if (typeof(this.adjacency[edge.source.id][edge.target.id]) === 'undefined') {  
        this.adjacency[edge.source.id][edge.target.id] = [];  
    }  
      
    exists = false;  
    this.adjacency[edge.source.id][edge.target.id].forEach(function(e) {  
            if (edge.id === e.id) { exists = true; }  
    });  
      
    if (!exists) {  
        this.adjacency[edge.source.id][edge.target.id].push(edge);  
    }  
      
    this.notify();  
    return edge;  
};  
      
Graph.prototype.newNode = function(data) {  
    var node = new Node(this.nextNodeId++, data);  
    this.addNode(node);  
    return node;  
};  
      
Graph.prototype.newEdge = function(source, target, data) {  
    var edge = new Edge(this.nextEdgeId++, source, target, data);  
    this.addEdge(edge);  
    return edge;  
};  
      
// find the edges from node1 to node2  
Graph.prototype.getEdges = function(node1, node2) {  
    if (typeof(this.adjacency[node1.id]) !== 'undefined'
        && typeof(this.adjacency[node1.id][node2.id]) !== 'undefined') {  
        return this.adjacency[node1.id][node2.id];  
    }  
      
    return [];  
};  
      
// remove a node and it's associated edges from the graph  
Graph.prototype.removeNode = function(node) {  
    if (typeof(this.nodeSet[node.id]) !== 'undefined') {  
        delete this.nodeSet[node.id];  
    }  
      
    for (var i = this.nodes.length - 1; i >= 0; i--) {  
        if (this.nodes[i].id === node.id) {  
            this.nodes.splice(i, 1);  
        }  
    }  
      
    this.detachNode(node);  
      
};  
      
// removes edges associated with a given node  
Graph.prototype.detachNode = function(node) {  
    var tmpEdges = this.edges.slice();  
    tmpEdges.forEach(function(e) {  
        if (e.source.id === node.id || e.target.id === node.id) {  
            this.removeEdge(e);  
        }  
    }, this);  
      
    this.notify();  
};  
      
// remove a node and it's associated edges from the graph  
Graph.prototype.removeEdge = function(edge) {  
    for (var i = this.edges.length - 1; i >= 0; i--) {  
        if (this.edges[i].id === edge.id) {  
            this.edges.splice(i, 1);  
        }  
    }  
      
    for (var x in this.adjacency) {  
        for (var y in this.adjacency[x]) {  
            var edges = this.adjacency[x][y];  
      
            for (var j=edges.length - 1; j>=0; j--) {  
                if (this.adjacency[x][y][j].id === edge.id) {  
                    this.adjacency[x][y].splice(j, 1);  
                }  
            }  
        }  
    }  
      
    this.notify();  
};  
      
/* Merge a list of nodes and edges into the current graph. eg. 
var o = { 
    nodes: [ 
        {id: 123, data: {type: 'user', userid: 123, displayname: 'aaa'}}, 
        {id: 234, data: {type: 'user', userid: 234, displayname: 'bbb'}} 
    ], 
    edges: [ 
        {from: 0, to: 1, type: 'submitted_design', directed: true, data: {weight: }} 
    ] 
} 
*/
Graph.prototype.merge = function(data) {  
    var nodes = [];  
    data.nodes.forEach(function(n) {  
        nodes.push(this.addNode(new Node(n.id, n.data)));  
    }, this);  
      
    data.edges.forEach(function(e) {  
        var from = nodes[e.from];  
        var to = nodes[e.to];  
      
        var id = (e.directed)  
            ? (id = e.type + "-" + from.id + "-" + to.id)  
            : (from.id < to.id) // normalise id for non-directed edges  
                ? e.type + "-" + from.id + "-" + to.id  
                : e.type + "-" + to.id + "-" + from.id;  
      
        var edge = this.addEdge(new Edge(id, from, to, e.data));  
        edge.data.type = e.type;  
    }, this);  
};  
      
Graph.prototype.filterNodes = function(fn) {  
    var tmpNodes = this.nodes.slice();  
    tmpNodes.forEach(function(n) {  
        if (!fn(n)) {  
            this.removeNode(n);  
        }  
    }, this);  
};  
      
Graph.prototype.filterEdges = function(fn) {  
    var tmpEdges = this.edges.slice();  
    tmpEdges.forEach(function(e) {  
        if (!fn(e)) {  
            this.removeEdge(e);  
        }  
    }, this);  
};  
      
      
Graph.prototype.addGraphListener = function(obj) {  
    this.eventListeners.push(obj);  
};  
      
Graph.prototype.notify = function() {  
    this.eventListeners.forEach(function(obj){  
        obj.graphChanged();  
    });  
};
  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved