"D3.js Advanced Series-2.0" bundle chart

Source: Internet
Author: User
Tags javascript array

Bundle is a rather peculiar layout in D3, with only two functions, and it needs to be used in conjunction with other layouts. This paper describes how to make the bundle diagram.

There are very few examples of bundle graphs, and it is easy to find: http://bl.ocks.org/mbostock/1044242


However, this example is somewhat complex, not easy to understand, and there is no corresponding explanatory text (D3 official on the internet, most of the examples do not have the corresponding text commentary), simply can not be used as a reference. This article provides a simple example of what the bundle diagram is and how it should be done.


The bundle graph has only two functions:


d3.layout.bundle (): creates a bundle chart layout.


Bundle (links): calculates the path based on the source and target of the array links.


The layout of a bundle is less than a function because it is often used in conjunction with other hierarchical layouts. The so-called hierarchical layout, refers to the use of nested structure (parent-child node relationship) to describe the node information, according to the hierarchical layout of the expansion of the layout is: Cluster diagram, package diagram, partition map, tree, Matrix tree diagram. Most commonly used with cluster diagrams, use the cluster diagram layout to compute the location of the nodes, and then use the bundle layout to calculate the line path. In other words, the bundle layout is only one thing to do:


Computes the path of the connection.


Let's give an example. China's high-speed rail has been opened in many cities, such as Beijing to Shanghai, Beijing to Guilin and so on. Now you have to make a diagram to show which city is the most densely populated by the high-speed rail.


1. Data

There are 9 cities:

var cities = {     Name: "",     children:[     {name: "Beijing"},{name: "Shanghai"},{name: "Hangzhou"},     {name: "Guangzhou"},{name: "Guilin"},{ Name: "Kunming"},     {name: "Chengdu"},{name: "Xi ' an"},{name: "Taiyuan"}     ]};


These 9 cities belong to a node that has a common parent node, the parent node name is empty, and the parent node is not drawn later. There is also an array of high-speed rail links to each city, as follows:

var railway = [{source: "Beijing", Target: "Shanghai"},{source: "Beijing", Target: "Guangzhou"},{source: "Beijing", Target: "Hangzhou"},{source: "Beijing", Targe T: "Xi ' an"},{source: "Beijing", Target: "Chengdu"},{source: "Beijing", Target: "Taiyuan"},{source: "Beijing", Target: "Guilin"},{source: "Beijing", Target: "Kunming "},{source:" Beijing ", Target:" Chengdu "},{source:" Shanghai ", Target:" Hangzhou "},{source:" Kunming ", Target:" Chengdu "},{source:" Xi ' an ", Target:" Taiyuan "}];// (This data is hypothetical and has not been investigated)


Source and target represent both ends of the high-speed rail respectively.

2. Layout (data conversion)

As mentioned earlier, the bundle layout is used in conjunction with other layouts, where it is federated with the cluster diagram layout. Create a cluster diagram layout and a bundle layout, respectively.

var cluster = D3.layout.cluster (). Size ([WIDTH/2]). Separation (function (A, B) {return (A.parent = = b.parent? 1: 2)/a.depth; }); var bundle = D3.layout.bundle ();


As can be seen from the parameters of the cluster diagram layout, the next node will be distributed round. Bundle diagram Layout No parameters can be set, just create, save in the variable bundle.


Compute nodes using the cluster diagram layout first:

var nodes = cluster.nodes (cities); Console.log (nodes);


Save the computed node array in nodes, and output the array, as shown in result 1, the first node has 9 child nodes, the other nodes have only one parent node, and no child nodes. This is the array of nodes to be used for the next bundle, but it is calculated using the cluster diagram layout.

Figure 1


The next step is to focus on using the array railway. Since both the source and target stored in railway have city names, they are first mapped to node objects in nodes. Write a function that replaces the node object with source and target in City name Railway.

function map (nodes, links) {var hash = [];for (var i = 0; i < nodes.length; i++) {Hash[nodes[i].name] = nodes[i];} var resultlinks = [];for (var i = 0; i < links.length; i++) {Resultlinks.push ({  source:hash[links[i].source], Targ et:hash[Links[i].target]});} return resultlinks;}


Using the array returned by this function, you can use the parameters for the bundle layout bundle:

var olinks = map (nodes, railway); Console.log (olinks); var links = bundle (olinks); Console.log (links);


The results of map () returned in Olinks,bundle () are saved in links, and the output is shown in 2 and Figure 3, which is the transformation before and after the line array transformation of the bundle diagram layout.

Figure 2


2, before the conversion, each item of the wired array has only two variables: source and target, and the content is the node object. For the first connection, it is from "Beijing" to "Shanghai". 3, after the conversion, the source and target are gone and replaced by 0, 1, 2, and become an array. Obviously, the first item of the array is the same as the content of the source, the last item is the same as the content of target, but there is an extra item in the middle (the red box in Figure 3). This extra item is calculated based on the parent node of source and target public. Thus, the array represents a path.


In fact, the bundle diagram layout based on the source and target of each line to calculate a line of lines for us, we can simply explain the role of the bundle layout as follows: The lines drawn with these paths can be more beautiful to say "which City of high-speed rail".

Figure 3


3. Draw

The data after the bundle layout transformation is well suited for plotting with d3.svg.line () and d3.svg.line.radial (), which is the line segment generator, which is the radial segment generator. In the pre-defined interpolation mode of line.interpolate (), one is called bundle, which is prepared for the bundle diagram.


Because this example uses a circle to compute a node array using the cluster diagram layout, a radial segment generator is used. First create a:

var line = D3.svg.line.radial (). Interpolate ("bundle"). Tension (.). Radius (function (d) {return d.y;}). Angle (function (d) {return d.x/180 * MATH.PI;});


This line segment generator is used to obtain the connection path. Next, add a grouping element <g>, which is used to put all the elements associated with the bundle diagram.

Gbundle = Svg.append ("G"). attr ("transform", "Translate (" + (WIDTH/2) + "," + (HEIGHT/2) + ")"); var color = D3.scale.catego RY20C ();//Color scale


Then, first add the line path in Gbundle:

var link = gbundle.selectall (". Link").  data (links).  enter ().  Append ("path")  . attr ("Class", "link")  . attr ("D", line);//Use Segment Builder


In the style of the line, adding transparency can show the "bundle" effect more in the connection. For example, the style is set to:

. link {fill:none;stroke:black;stroke-opacity:. 5;stroke-width:8px;}


The drawing results of line 4 are shown.

Figure 4


Finally, add the nodes to the diagram. The node is represented by a circle, which is written with the name of the city. First, bind the array of nodes and add the corresponding <g> elements.

var node = gbundle.selectall (". Node")  . Data (Nodes.filter (function (d) {return!d.children;}))  . Enter ()  . Append ("G").  attr ("Class", "Node")  . attr ("Transform", function (d) {return "rotate (" + (d.x-90) + ") Translate (" + D.y + ")" + "Rotate (" + (90-d.x) + ")";   } ";


Note that the bound array is a filtered array of nodes. The filter here is a function of the JavaScript array object itself, and the bold part indicates that only nodes that have no child nodes are bound , that is, the public parent nodes of the 9 cities are not drawn. Then just add <circle> and <text> in the grouping element <g>.

Node.append ("Circle")  . attr ("R")  . Style ("Fill", function (d,i) {return color (i);}); Node.append ("text"). attr ("dy", ". 2em"). Style ("Text-anchor", "Middle"). Text (function (d) {return d.name;});


As shown in result 5. Thanks to the most high-speed rail lines in Beijing, the most densely connected circle in Beijing is like tying a lot of ropes here.

Figure 5


When nodes and wires become much more complex, it becomes an example at the beginning of this article. As I said at the beginning of this article, the completion of that example is too high to provide a reference at all. I hope the example of this article can give you a reference example of bundle diagram.


Please click on the following link to view the full code:


Http://www.ourd3js.com/demo/G-2.0/bundle.html


Thank you for reading.

Document Information
    • Copyright Notice: Attribution (by)-Non-commercial (NC)-No deduction (ND)
    • Published: March 20, 2015
    • More content: our D3. JS-Data Visualization special station and CSDN personal blog
    • Remark: This article is published in our D3. JS, reproduced please indicate the source, thank you

"D3.js Advanced Series-2.0" bundle chart

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.