[Web chart Series 4] graphic layout-js Design and Implementation of Layout

Source: Internet
Author: User

You can locate the chart, VML, SVG, and HTML5 canvas of the browser in different ways.

If you use the existing JS Library (various libraries that implement JS charts to summarize and compare), the API calling method is certainly different.

For example, you can use addfigure and setposition in draw2d to set the position of an image.

It is obviously not wise to mix layout in a specific technology or library.

Split, layout is applicable to any drawing. It is discussed in this chapter.

The idea of implementation is actually very simple. It maintains a JS object (graph ). Record the node and edge information in this object. The node contains the following information: id -- symbol X -- X coordinate Y -- y coordinate shape -- the drawn figure, before creating a graph node, you must maintain the information of the graph node. Graph example

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 node2Graph.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 graphGraph.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 nodeGraph.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 graphGraph.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();});};

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.