【D3.js数据可视化系列教程】(三十四)-- sankey图

好多没看懂。先把理解的放着吧

<!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>


 

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 27
    评论
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值