好多没看懂。先把理解的放着吧
<!DOCTYPE html> <head> <meta charset="utf-8"> <title>Sankey Diagram4</title> <style> #chart { height: 500px; } .node rect { cursor: move; fill-opacity: .9; shape-rendering: crispEdges; } .node text { pointer-events: none; text-shadow: 0 1px 0 #fff; } .link { fill: none; stroke: #000; stroke-opacity: .2; } .link:hover { stroke-opacity: .5; } </style> </head> <body> <link type="text/css" href="http://localhost:8080/spring/css/style.css" /> <script src="http://localhost:8080/spring/js/d3.v3.js"></script> <script src="http://localhost:8080/spring/js/sankey.js"></script> <p id="chart"> <script type="text/javascript"> var margin = {top: 1, right: 1, bottom: 6, left: 1}, width = 960 - margin.left - margin.right, height = 500 - margin.top - margin.bottom; //(1)数字格式化函数 var formatNumber = d3.format(",.0f"),//将数字转化为字符串(小数四舍五入),逗号可以允许使用千分位来分隔,例如:1391.989->1,392 //下面只是为提示条的数字格式化 format = function(d) { console.log(d+"->"+formatNumber(d)); return formatNumber(d) + " TWh"; },//TWh是太瓦时,描述的电量分配的例子,当然用这个单位 color = d3.scale.category20(); var svg = d3.select("#chart")//ID选择器 .append("svg") .attr("width", width + margin.left + margin.right) .attr("height", height + margin.top + margin.bottom) .append("g") .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); //(2)生成sankey布局 var sankey = d3.sankey() .nodeWidth(15)//每个资源块的水平像素宽度 .nodePadding(10)//资源块间的纵向间距 .size([width, height]); var path = sankey.link(); d3.json("http://localhost:8080/spring/D3data/sankey.json", function(energy) { //(3)sankey加载节点和链接数据 sankey .nodes(energy.nodes) .links(energy.links) .layout(32);//布局均匀化,数值大中间的块就会向下移动,比较均衡 //(4)sankey设置链接属性 var link = svg.append("g").selectAll(".link") .data(energy.links) .enter().append("path") .attr("class", "link") .attr("d", path)//链接的路径设置已经被sankey封装了,这里调用之后就可以生成连线呢的路径 //下面这句生成线的宽度,//线的宽度按照线端点两端块较小者扩宽,但为啥偏移max(1, d.dy)? .style("stroke-width", function(d) { return Math.max(1, d.dy); }) .sort(function(a, b) { return b.dy - a.dy; });//这句去掉效果一样不知为啥? //(5)sankey设置链接提示 link.append("title") .text(function(d) { return d.source.name + " → " + d.target.name + "\n" + format(d.value); }); //(6)拖动 var node = svg.append("g").selectAll(".node") .data(energy.nodes) .enter().append("g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }) .call(d3.behavior.drag() .origin(function(d) { return d; })//拖动行为保存鼠标的位置,并在拖动过程中的启动元件的位置之间的偏移量。如果是空的起源访问,然后设置元素的位置就拖鼠标的位置,这可能会导致对大量元素有明显的跳动 .on("dragstart", function() { //这句是什么? this.parentNode.appendChild(this); }) .on("drag", dragmove)); //(7)块 node.append("rect") .attr("height", function(d) { return d.dy; }) .attr("width", sankey.nodeWidth())//刚才设置的块的宽度 .style("fill", function(d) { return d.color = color(d.name.replace(/ .*/, "")); }) .style("stroke", function(d) { return d3.rgb(d.color).darker(2); })//较深 .append("title") .text(function(d) { return d.name + "\n" + format(d.value); }); //(8)文字 node.append("text") .attr("x", -6) .attr("y", function(d) { return d.dy / 2; }) .attr("dy", ".35em") .attr("text-anchor", "end")//文字在左边(中轴右边的) .attr("transform", null) .text(function(d) { return d.name; }) .filter(function(d) { return d.x < width / 2; })//除去在中轴左边的 .attr("x", 6 + sankey.nodeWidth()) .attr("text-anchor", "start");//文字在右边 //(9)拖动 function dragmove(d) { d3.select(this).attr("transform", "translate(" + d.x + "," + (d.y = //下面的纵坐标调整值是怎么计算的? Math.max(0, Math.min( height - d.dy, d3.event.y ))) + ")"); sankey.relayout();//重新布局,线上下的位置调整 link.attr("d", path);//更新路径 } }); </script> </body>