首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Web Chart 入門(四):圖形佈局 Layout 的 JavaScript 設計實現

     編輯:Java 相關知識

前言:為什麼需要獨立的 Layout 層?

瀏覽器端圖表繪制技術多樣(VML、SVG、HTML5 Canvas),各類 JS 圖表庫(如 draw2d、D3、ECharts)API 差異巨大。若將佈局邏輯耦合在具體繪制庫中,將難以復用與維護。

核心思想:將「佈局計算」與「具體繪制」解耦。維護一個純 JS 對象模型(Graph)記錄節點、邊的拓撲信息與坐標,繪制庫僅負責根據該模型渲染。

Graph 數據模型設計

var Graph = function() {
    this.nodeSet = {};      // id -> Node 映射,便於 O(1) 查找
    this.nodes = [];        // 節點列表
    this.edges = [];        // 邊列表
    this.adjacency = {};    // 鄰接表:sourceId -> {targetId -> [Edge]}
    this.nextNodeId = 0;    // 自增 ID 生成器
    this.nextEdgeId = 0;
    this.eventListeners = []; // 變更通知機制
};

// 節點:id + 業務數據 + 可選 shape(繪制庫具體圖形引用)
var Node = function(id, data) {
    this.id = id;
    this.data = data || {};
};

// 邊:id + source/target 節點引用 + 業務數據
var Edge = function(id, source, target, data) {
    this.id = id;
    this.source = source;
    this.target = target;
    this.data = data || {};
};

核心操作 API

增刪改查

// 添加節點(去重)
Graph.prototype.addNode = function(node) {
    if (!this.nodeSet[node.id]) {
        this.nodes.push(node);
    }
    this.nodeSet[node.id] = node;
    this.notify();
    return node;
};

// 添加邊(去重)
Graph.prototype.addEdge = function(edge) {
    var exists = this.edges.some(function(e) { return e.id === edge.id; });
    if (!exists) this.edges.push(edge);

    // 維護鄰接表
    var adj = this.adjacency[edge.source.id] = this.adjacency[edge.source.id] || {};
    var list = adj[edge.target.id] = adj[edge.target.id] || [];
    if (!list.some(function(e) { return e.id === edge.id; })) {
        list.push(edge);
    }
    this.notify();
    return edge;
};

// 工廠方法
Graph.prototype.newNode = function(data) {
    return this.addNode(new Node(this.nextNodeId++, data));
};
Graph.prototype.newEdge = function(source, target, data) {
    return this.addEdge(new Edge(this.nextEdgeId++, source, target, data));
};

查詢與過濾

// 獲取兩節點間的所有邊
Graph.prototype.getEdges = function(node1, node2) {
    return (this.adjacency[node1.id] && this.adjacency[node1.id][node2.id]) || [];
};

// 刪除節點及關聯邊
Graph.prototype.removeNode = function(node) {
    delete this.nodeSet[node.id];
    this.nodes = this.nodes.filter(function(n) { return n.id !== node.id; });
    this.detachNode(node);
};

// 刪除邊
Graph.prototype.removeEdge = function(edge) {
    this.edges = this.edges.filter(function(e) { return e.id !== edge.id; });
    // 清理鄰接表
    for (var x in this.adjacency) {
        for (var y in this.adjacency[x]) {
            this.adjacency[x][y] = this.adjacency[x][y].filter(function(e) { return e.id !== edge.id; });
        }
    }
    this.notify();
};

批量合併與事件機制

// 合併外部圖數據(含節點 id 與邊 from/to 索引)
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 ? (e.type + "-" + from.id + "-" + to.id)
                            : (from.id < to.id ? 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) {
    this.nodes.slice().forEach(function(n) { if (!fn(n)) this.removeNode(n); }, this);
};
Graph.prototype.filterEdges = function(fn) {
    this.edges.slice().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(); });
};

設計優勢

  • 技術無關:Graph 模型不依賴任何繪制庫,可服務於 SVG、Canvas、WebGL 等任意渲染器
  • 佈局算法可插拔:力導向、層次、圓形等佈局算法只需消費 Graph 模型,輸出坐標
  • 雙向綁定友好:notify() 機制便於 UI 同步更新
  • 可序列化:純數據結構易於存儲、傳輸、撤銷/重做

應用場景

流程圖編輯器、拓撲圖可視化、知識圖譜探索、組織架構圖、工作流設計器等所有「節點+連線」類應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved