# D3实例3

# d3线段图加点展示

<html>
	<body></body>
	<style>
		*{
			margin:0;
			padding:0;
			
		}
		.line{
			fill: none;    
			stroke: steelblue;
			stroke-width: 2;
		}
		
		.axis path, .axis line { 
			stroke: #409EFF;
		}
	</style>
	<script src="https://d3js.org/d3.v5.min.js"></script>
	<script>
		//数据 界面 映射 刻度尺 绑定
		let data=[[],[]]
		
		function createdata(){
			
			data=[[],[]];
			for(let i=0;i<10;i++){
				var a =parseInt(Math.random()*10) 
				var b =parseInt(Math.random()*10) 
				data[0].push(a)
				data[1].push(b)
				
			}
			var tem =svg.selectAll("path.line").data(data)
			tem.enter()
				.append("path").merge(tem)
				.transition().duration(1000)
				.style("stroke",(d,i)=>colors(i)).attr("class","line").attr("d",(d,i)=>{
					return line(d)
			})
			// svg.selectAll("circle.dot").remove()
			
			for(let i=0;i<data.length;i++){
				console.log(data[i])
				var tem1 =svg.selectAll(`circle.dot${i}`)
				var tem2=tem1.data(data[i]);
				tem2.enter().append("circle").merge(tem2)
				.transition().duration(1000)
				.attr("class",`dot${i}`)
				.style("fill",(d)=>{
					return colors(i)
				})
				.attr("cx",(d,i)=>xscale(i))
				.attr("cy",d=>yscale(d))
				.attr("r",10)
			
			}
			
			
		}
		
		console.log(data)
		
		var colors = d3.scaleOrdinal(d3.schemeCategory10);
		var margin=30,
			width =600,
			height =500
			
		var svg =d3.select("body").append("svg")
					.attr("width",width).attr("height",height)
					.style("border","1px solid deepskyblue")
		
			
		var xscale = d3.scaleLinear().domain([0,10]).range([margin,width-margin])
		var yscale =d3.scaleLinear().domain([0,10]).range([height-margin,margin])
		
		var xaxis = d3.axisBottom().scale(xscale)
		var yaxis = d3.axisLeft().scale(yscale)
		
		svg.selectAll("line.help").data([0,1,2,3,4,5,6,7,8,9,10]).enter().append("line")
		.attr("class","help").attr("x1",xscale(0)).attr("y1",d=>yscale(d))
		.attr("x2",xscale(10)).attr("y2",d=>yscale(d)).attr("stroke","#409EFF")
		
		// yaxis(svg)
		svg.append("g").attr("transform",`translate(0,${height-margin})`)
		.classed("axis",true).call(xaxis)
		svg.append("g").attr("transform",`translate(30,0)`).call(yaxis)
		.classed("axis",true)
		
		var line=d3.line().x((d,i)=>xscale(i)).y(d=>yscale(d)).curve(d3.curveCardinal)
		
		
		
		
	
		
		make()
		function make(){
			createdata()
		}
		
		
			
	</script>
	<button onclick="make()">dianji</button>
</html>

# 总结

  • 数据 界面 映射 刻度尺 绑定
  • merge的使用需要注意
var tem =svg.selectAll("path.line").data(data)
			tem.enter()
				.append("path").merge(tem)
  • path路径绘制出的曲线/折线/面积图是二维数组,而其中的circle(包括散点图)和pie则不需要是二维数组的数据
  • 更新和新增 与合并
function render(data) { // <- B
	var bars = d3.select("body").selectAll("div.h-bar") // <- C
			.data(data); // Update <- D
	// Enter
	bars.enter() // <- E
			.append("div") // <- F
				.attr("class", "h-bar") // <- G
		.merge(bars) // Enter + Update <- H
			.style("width", function (d) {
				return (d * 3) + "px"; // <- I
			})
			.text(function (d) {
				return d; // <- J
			});
	// Exit
	bars.exit() // <- K
			.remove();
}

//方法二
 function render(data){
	console.log(data)
	var bars = d3.select("body").selectAll("div.h-bar").data(data)
	bars.text(function(d,i){
		return d
	}).style("width",(d,i)=>{
		return  (d * 3) + "px"
	})
	bars.enter().append("div").attr("class", "h-bar").text(function(d,i){
		return d
	}).style("width",(d,i)=>{
		return  (d * 3) + "px"
	})
	bars.exit().remove()
 }

# 面积图

<html>
	<body></body>
	<style>
		*{
			margin:0;
			padding:0;
			
		}
		.line{
			fill: none;    
			stroke: steelblue;
			stroke-width: 2;
		}
		
		.axis path, .axis line { 
			stroke: #409EFF;
		}
	</style>
	<script src="https://d3js.org/d3.v5.min.js"></script>
	<script>
		//数据 界面 映射 刻度尺 绑定
		let data=[[],[]]
		
		function createdata(){
			
			data=[[],[]];
			for(let i=0;i<10;i++){
				var a =parseInt(Math.random()*10) 
				var b =parseInt(Math.random()*10) 
				data[0].push(a)
				data[1].push(b)
				
			}
			var tem =svg.selectAll("path.line").data(data)
			tem.enter()
				.append("path").merge(tem)
				.transition().duration(1000)
				.style("stroke",(d,i)=>colors(i)).attr("class","line").attr("d",(d,i)=>{
					return line(d)
			})
			// svg.selectAll("circle.dot").remove()
			var temarea =svg.selectAll("path.area").data(data)
			temarea.enter()
				.append("path").merge(temarea).classed("area",true)
				.style("fill",(d,i)=>colors(i)).attr("opacity","0.8").attr("d",(d,i)=>{
						return area(d)
				})
			
			
			for(let i=0;i<data.length;i++){
				console.log(data[i])
				var tem1 =svg.selectAll(`circle.dot${i}`)
				var tem2=tem1.data(data[i]);
				tem2.enter().append("circle").merge(tem2)
				.transition().duration(1000)
				.attr("class",`dot${i}`)
				.style("fill",(d)=>{
					return colors(i)
				})
				.attr("cx",(d,i)=>xscale(i))
				.attr("cy",d=>yscale(d))
				.attr("r",10)
			
			}
			
			
		}
		
		console.log(data)
		
		var colors = d3.scaleOrdinal(d3.schemeCategory10);
		var margin=30,
			width =600,
			height =500
			
		var svg =d3.select("body").append("svg")
					.attr("width",width).attr("height",height)
					.style("border","1px solid deepskyblue")
		
			
		var xscale = d3.scaleLinear().domain([0,10]).range([margin,width-margin])
		var yscale =d3.scaleLinear().domain([0,10]).range([height-margin,margin])
		
		var xaxis = d3.axisBottom().scale(xscale)
		var yaxis = d3.axisLeft().scale(yscale)
		
		svg.selectAll("line.help").data([0,1,2,3,4,5,6,7,8,9,10]).enter()
			.append("line").attr("class","help").attr("x1",xscale(0))
			.attr("y1",d=>yscale(d)).attr("x2",xscale(10))
			.attr("y2",d=>yscale(d)).attr("stroke","#409EFF")
		
		// yaxis(svg)
		svg.append("g").attr("transform",`translate(0,${height-margin})`)
			.classed("axis",true).call(xaxis)
		svg.append("g").attr("transform",`translate(30,0)`).call(yaxis)
			.classed("axis",true)
		
		var line=d3.line().x((d,i)=>xscale(i)).y(d=>yscale(d))
			.curve(d3.curveCardinal.tension(0.8))
		var area=d3.area().x((d,i)=>xscale(i)).y0((d)=>yscale(0))
			.y1(d=>yscale(d)).curve(d3.curveCardinal.tension(0.8))
		
		
		
		
		
	
		
		make()
		function make(){
			createdata()
		}
		
		
			
	</script>
	<button onclick="make()">dianji</button>
</html>

# d3散点图

<html>
	<body></body>
	<style>
		*{
			margin:0;
			padding:0;
			
		}
		.line{
			fill: none;    
			stroke: steelblue;
			stroke-width: 2;
		}
		
		.axis path, .axis line { 
			stroke: #409EFF;
		}
	</style>
	<script src="https://d3js.org/d3.v5.min.js"></script>
	<script>
		//数据 界面 映射 刻度尺 绑定
		let data=[[],[],[],[]]
		var colors = d3.scaleOrdinal(d3.schemeCategory10);
		var margin=30,
			width =600,
			height =500
			
		
		function createdata(){
			
			data=[[],[],[],[]];
			for(let i=0;i<10;i++){
				var a =parseFloat(Math.random()*10) 
				var b =parseFloat(Math.random()*10) 
				var c =parseFloat(Math.random()*10) 
				var d =parseFloat(Math.random()*10)
				var e =parseFloat(Math.random()*10) 
				var f =parseFloat(Math.random()*10)
				var g =parseFloat(Math.random()*10)
				var h =parseFloat(Math.random()*10)
				data[0].push({x:a,y:b})
				data[1].push({x:c,y:d})
				data[2].push({x:e,y:f})
				data[3].push({x:g,y:h})

				
				
			}
			console.log(data)
			for(let i=0;i<data.length;i++){
				var tem =svg.selectAll("path.dot"+i).data(data[i])
				tem.enter()
					.append("path").merge(tem).attr("class","dot"+i)
					.transition().duration(1000)// <-C
					    .attr("transform", function(d){
							console.log(d)
							console.log(xscale(d.x))
					        return "translate(" // <-D
					                + xscale(d.x)
					                + ","
					                + yscale(d.y)
					                + ")";
					    })
					.style("fill",(d)=>colors(i))
					.attr("d", d3.symbol().type(_symbolTypes(i)))
			}
			
	
			
			
		}
		
		console.log(data)
		
    var svg =d3.select("body").append("svg")
					.attr("width",width).attr("height",height)
					.style("border","1px solid deepskyblue")
		
		
		var xscale = d3.scaleLinear().domain([0,10]).range([margin,width-margin])
		var yscale =d3.scaleLinear().domain([0,10]).range([height-margin,margin])
		
		var xaxis = d3.axisBottom().scale(xscale)
		var yaxis = d3.axisLeft().scale(yscale)
		
		svg.append("g").attr("transform",`translate(0,${height-margin})`).classed("axis",true).call(xaxis)
		svg.append("g").attr("transform",`translate(30,0)`).call(yaxis).classed("axis",true)
		var _symbolTypes = d3.scaleOrdinal() // <-A
		        .range([d3.symbolCircle,
		            d3.symbolCross,
		            d3.symbolDiamond,
		            d3.symbolSquare,
		            d3.symbolStar,
		            d3.symbolTriangle,
		            d3.symbolWye
		        ]);
		
	
	
		
		make()
		function make(){
			createdata()
		}
		
		
			
	</script>
	<button onclick="make()">dianji</button>
</html>

# 总结

  • 一维数组
  • d属性画出的图形用d3.symbol().type(xxx)
  • 位置需要用transform来绘制
  • 绘制散点图可以d3提供很多内置的样式
  • d3.symbolCircle,d3.symbolCross
  • d3.symbolDiamond,d3.symbolSquare
  • d3.symbolStar,d3.symbolTriangle,d3.symbolWye
  • d属性注意是直接给出d3.symbol().type(xxx)而不是(d,i)=>再给出

# 气泡图

典型的用于展示三维数据的可视化控件

<html>
	<body></body>
	<style>
		*{
			margin:0;
			padding:0;
			
		}
		.line{
			fill: none;    
			stroke: steelblue;
			stroke-width: 2;
		}
		
		.axis path, .axis line { 
			stroke: #409EFF;
		}
	</style>
	<script src="https://d3js.org/d3.v5.min.js"></script>
	<script>
		//数据 界面 映射 刻度尺 绑定
		let data=[]
		var colors = d3.scaleOrdinal(d3.schemeCategory10);
		var margin=30,
			width =600,
			height =500
			
		
		function createdata(){
			
			data=[];
			for(let i=0;i<30;i++){
				var a =parseFloat(Math.random()*10) 
				var b =parseFloat(Math.random()*10) 
				var c =parseInt(Math.random()*10) 
				
				data.push({x:a,y:b,r:c})
			
					
			}
			console.log(data)
			var tem =svg.selectAll("circle.dot").data(data)
			tem.enter().append("circle").merge(tem).attr("class","dot")
			.transition().duration(1000)
			.attr("fill",(d,i)=>colors(i))
			.attr("cx",d=>xscale(d.x))
			.attr("cy",d=>yscale(d.y))
			.attr("r",d=>2*d.r)
	
		}
		
		console.log(data)
		
    var svg =d3.select("body").append("svg")
					.attr("width",width).attr("height",height)
					.style("border","1px solid deepskyblue")
		
		
		var xscale = d3.scaleLinear().domain([0,10]).range([margin,width-margin])
		var yscale =d3.scaleLinear().domain([0,10]).range([height-margin,margin])
		
		var xaxis = d3.axisBottom().scale(xscale)
		var yaxis = d3.axisLeft().scale(yscale)
		
		svg.append("g").attr("transform",`translate(0,${height-margin})`).classed("axis",true).call(xaxis)
		svg.append("g").attr("transform",`translate(30,0)`).call(yaxis).classed("axis",true)

		
		make()
		function make(){
			createdata()
		}
		
		
			
	</script>
	<button onclick="make()">dianji</button>
</html>

# 柱形图

<html>
	<body></body>
	<style>
		*{
			margin:0;
			padding:0;
			
		}
		.line{
			fill: none;    
			stroke: steelblue;
			stroke-width: 2;
		}
		
		.axis path, .axis line { 
			stroke: #409EFF;
		}
	</style>
	<script src="https://d3js.org/d3.v5.min.js"></script>
	<script>
		//数据 界面 映射 刻度尺 绑定
		let data=[]
		var colors = d3.scaleOrdinal(d3.schemeCategory10);
		var margin=30,
			width =600,
			height =500
			
		
		function createdata(){
			
			data=[];
			for(let i=0;i<12;i++){
				var a =parseInt(Math.random()*10+1) 
				
				
				data.push(a)
			
					
			}
			console.log(data)
			
			
			var tem =svg.selectAll("rect.dot").data(data)
			tem.enter().append("rect").merge(tem).attr("class","dot")
			.transition().duration(1000)
			.attr("fill",(d,i)=>colors(i))
			.attr("x",(d,i)=>xscale(i))
			.attr("y",d=>height-yscale(d)-margin)
			.attr("height",d=>yscale(d))
			.attr('width', xscale.bandwidth())

			
		}
		
		console.log(data)
		
    var svg =d3.select("body").append("svg")
					.attr("width",width).attr("height",height)
					.style("border","1px solid deepskyblue")
		
		
		

		
	var yscale =d3.scaleLinear().domain([0,10]).range([height-margin,margin])
	
	
	const xscale = d3.scaleBand().range([margin, width-margin])
	.domain([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]).padding(0.2)
	var xaxis = d3.axisBottom().scale(xscale)
	var yaxis = d3.axisLeft().scale(yscale)
	
	svg.append("g").attr("transform",`translate(0,${height-margin})`).classed("axis",true).call(xaxis)
	svg.append("g").attr("transform",`translate(30,0)`).call(yaxis).classed("axis",true)
		
		
		make()
		function make(){
			createdata()
		}
		
		
			
	</script>
	<button onclick="make()">dianji</button>
</html>

# 总结

  • 注意x轴,需要和数据绑定,要不然位置会出现问题

# 饼图

<html>
	<body></body>
	<style>
		*{
			margin:0;
			padding:0;
			
		}
		.line{
			fill: none;    
			stroke: steelblue;
			stroke-width: 2;
		}
		
		.axis path, .axis line { 
			stroke: #409EFF;
		}
	</style>
	<script src="https://d3js.org/d3.v5.min.js"></script>
	<script>
		data1=[];
		for(let i=0;i<5;i++){
			var math=parseInt( Math.random()*10)+1
			data1.push(math)
		}
		
		endAngle = 2* Math.PI
		
		var data = [ // <-B
            {startAngle: 0, endAngle: 0.1 * endAngle},
            {startAngle: 0.1 * endAngle, endAngle: 0.2 * endAngle},
            {startAngle: 0.2 * endAngle, endAngle: 0.4 * endAngle},
            {startAngle: 0.4 * endAngle, endAngle: 0.6 * endAngle},
            {startAngle: 0.6 * endAngle, endAngle: 0.7 * endAngle},
            {startAngle: 0.7 * endAngle, endAngle: 0.9 * endAngle},
            {startAngle: 0.9 * endAngle, endAngle: endAngle}
        ];
		var arc =  d3.arc().outerRadius(100).innerRadius(20)
		
		var pie= d3.pie().value(d=>{
				console.log(d)
				return d
		})
		var pieData= pie(data1)
		var colors = d3.scaleOrdinal(d3.schemeCategory10);
		var margin=30,
			width =600,
			height =500
			
		var svg =d3.select("body").append("svg")
					.attr("width",width).attr("height",height)
					.style("border","1px solid deepskyblue")
					
		svg.append("g").attr("transform",`translate(100,100)`)
		.selectAll("path.arc").data(data).enter().append("path")
			.attr("class","arc").attr("d",(d,i)=>arc(d)).attr("fill",(d,i)=>colors(i))
			
		svg.append("g").attr("transform",`translate(100,300)`)
		.selectAll("path.arc").data(pieData).enter().append("path")
			.attr("class","arc").attr("d",(d,i)=>arc(d)).attr("fill",(d,i)=>colors(i))
		
		svg.append("g").attr("transform",`translate(300,100)`)
		.selectAll("path.arc2").data(pieData).enter().append("path").attr("class","arc2")
			.transition().duration(3000).attrTween('d', function(d, i) {
				console.log(d)
				let interpolate = d3.interpolate(d.startAngle, d.endAngle);
				return function(t) {
					d.endAngle = interpolate(t);
					return arc(d);
				}
			}).attr("fill",(d,i)=>colors(i))
		
		svg.append("g").attr("transform",`translate(300,300)`)
		.selectAll("path.arc2").data(pieData).enter().append("path").attr("class","arc2")
			.transition().duration(3000).attrTween('d', function(d, i) {
				// console.log(d)
				var start ={startAngle:0,endAngle:0};
				
				var interpolate =d3.interpolate(start,d)
				// console.log(interpolate)
				return function(t){
					return arc(interpolate(t))
				}
			}).attr("fill",(d,i)=>colors(i))
	</script>
	
</html>

# 总结

  • 饼图如果不用d3.pie只使用d3.arc的话,需要精确好它的初始角度和结束角度
  • d3.arc().outerRadius(x).innerRadius(y)控制圆的半径和圆是否空心
  • pie = d3.pie().value()绑定原始数据,value中根据原始数据的某一项进行处理
  • piedata = pie(data)
  • 最后把这个piedata传给绘制的path
  • 动画效果可以使用中间帧函数attrTween来实现
  • 另外注意可以使用arc.centroid(d)来获取设置给饼图配置的文字位置
var arcs=svg.append("g").attr("transform",`translate(300,300)`)
		.selectAll("path.arc2").data(pieData).enter()
		
arcs.append("path").attr("class","arc2").transition().duration(1000)
	.attrTween('d', function(d, i) {
		// console.log(d)
		var start ={startAngle:0,endAngle:0};
		
		var interpolate =d3.interpolate(start,d)
		// console.log(interpolate)
		return function(t){
			return arc(interpolate(t))
		}
	}).attr("fill",(d,i)=>colors(i))
	
arcs
	.append('text').transition().duration(3000)
	.attr('transform', function(d) {
	  const x = arc.centroid(d)[0] * 1; // 文字的x坐标
	  const y = arc.centroid(d)[1] * 1;
	  return `translate(${x},${y})`;
	})

	.attr('text-anchor', 'middle')
	.text((d,i) => {
		return i
	});

# 堆叠面积图

<html>
	<body></body>
	<style>
		*{
			margin:0;
			padding:0;
			
		}
		
	</style>
	<script src="https://d3js.org/d3.v5.min.js"></script>
	<script>
		let data=[]
		for(let i=0;i<11;i++){
				var a =parseInt(Math.random()*10)+1 
				var b =parseInt(Math.random()*10)+1 
				var c =parseInt(Math.random()*10)+1 
				var d =parseInt(Math.random()*10)+1
				data.push({x:a,y:b,z:c,f:d})
			}
		console.log(data)
		var colors = d3.scaleOrdinal(d3.schemeCategory10);
		var margin=30,
			width =600,
			height =500
		var svg =d3.select("body").append("svg")
					.attr("width",width).attr("height",height)
					.style("border","1px solid deepskyblue")
		
		
		var xscale = d3.scaleLinear().domain([0,10]).range([margin,width-margin])
		var yscale =d3.scaleLinear().domain([0,40]).range([height-margin,margin])
		
		var xaxis = d3.axisBottom().scale(xscale)
		var yaxis = d3.axisLeft().scale(yscale)
		
		svg.append("g").attr("transform",`translate(0,${height-margin})`)
			.classed("axis",true).call(xaxis)
		svg.append("g").attr("transform",`translate(30,0)`)
			.call(yaxis).classed("axis",true)
		
		var stack =d3.stack().keys(["x","y","z","f"]).offset(d3.stackOffsetNone)(data)
		console.log(stack)
		var area=d3.area().x((d,i) => xscale(i))
						.y0(d =>{ 
							return yscale(d[0])
						})
						.y1(d => yscale(d[1])).curve(d3.curveBasis)
						
		svg.selectAll("path.area").data(stack).enter()
			.append("path").attr("class","area")
			.attr("d",(d,i)=>area(d)).attr("fill",(d,i)=>colors(i))
	
	</script>
	
</html>

# 总结

  • 利用d3.stack()把给的一维数组转化成二维,并且可以方便堆叠面积使用,里面的offset可以配置图形的形状
  • 把转换后的数据填充到path中
  • d3.stack需要绑定一个keys值

# treemap图

<!DOCTYPE html>
<style>
form{
	font-family:"Helvetica Neue",Arical, sans-serif;
}
 
svg{
	font: 10px sans-serif;
}
</style>
<svg width="1200" height="600"></svg>
<form>
	
</form>
<script src="http://d3js.org/d3.v5.min.js"></script>
<script>
var svg=d3.select("svg");
var width=1200,height=550;
var colors = d3.scaleOrdinal(d3.schemeCategory10)
var data={
"name":"gen",
"children":[
{
	"name":"num1",
	"children":[{"name":"num1-1","size":15},{"name":"num1-2","size":"5"}]
},
{
	"name":"num2",
	"children":[{"name":"num2-1","size":4},{"name":"num2-2","size":7},
			{"name":"num2-3","size":2},{"name":"num2-4","size":5}
	]
},
{
	"name":"num3",
	"size":10
},
{
	"name":"num4",
	"size":10
},
{
	"name":"num5",
	"size":10
}
]
};
var treemap=d3.treemap()
	.tile(d3.treemapResquarify)//布局样式,默认 d3.treemapResquarify
	.size([width,height])//宽高
	.round(true)//启用或者禁止四舍五入默认false
	.paddingInner(10)
	

 
var hi=d3.hierarchy(data)
.sum(function(d){ return d.size; })

treemap(hi);
var cell=svg.selectAll("g")
.data(hi.leaves())
.enter().append("g");
 console.log(hi.leaves())
 var arr=[]
cell.append("rect")
	.attr("x",function(d){ return d.x0; })
	.attr("y",function(d){ return d.y0; })
	.attr("width",function(d){ return d.x1-d.x0; })
	.attr("height",function(d){ return d.y1-d.y0; })
	.attr("fill",function(d,i) {
		return colors(d.parent.data.name) 
		
	})
 
cell.append("text")
	.attr("x",function(d) {return d.x0;})
	.attr("y",function(d) {return d.y0;})
	.attr("dx","0.5em")
	.attr("dy","1.5em")
	.attr("fill","#FFF")
	.attr("font-size",12)  
	.text(function(d){   return d.data.name+":"+d.data.size;
} );
	

</script>

# 总结

  • d3.treemap()设置样式
  • d3.hierarchy(data)设置参考
  • treemap(hi)传递参数
  • hi.leaves()根据这个绘制矩形

# tree

 
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
 
<title>CodePen - d3树图</title>
<script>
  window.console = window.console || function(t) {};
</script>
<!-- <script>
  if (document.location.search.match(/type=embed/gi)) {
    window.parent.postMessage("resize", "*");
  }
</script> -->
</head>
<body translate="no">
<svg width='1280' height="860"></svg>
<script src='https://cdnjs.cloudflare.com/ajax/libs/d3/5.9.2/d3.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js'></script>
<script id="rendered-js">
      var dataset = {
  name: "中国",
  children: [
  {
    name: "浙江",
    children: [
    { name: "杭州", value: 100 },
    { name: "宁波", value: 100 },
    { name: "温州", value: 100 },
    { name: "绍兴", value: 100 }] },
 
 
  {
    name: "广西",
    children: [
    {
      name: "桂林",
      children: [
      { name: "秀峰区", value: 100 },
      { name: "叠彩区", value: 100 },
      { name: "象山区", value: 100 },
      { name: "七星区", value: 100 }] },
 
 
    { name: "南宁", value: 100 },
    { name: "柳州", value: 100 },
    { name: "防城港", value: 100 }] },
 
 
  {
    name: "黑龙江",
    children: [
    { name: "哈尔滨", value: 100 },
    { name: "齐齐哈尔", value: 100 },
    { name: "牡丹江", value: 100 },
    { name: "大庆", value: 100 }] },
 
 
  {
    name: "新疆",
    children:
    [
    { name: "乌鲁木齐" },
    { name: "克拉玛依" },
    { name: "吐鲁番" },
    { name: "哈密" }] }] };
 
 
 
 
 
var marge = { top: 60, bottom: 0, left: 30, right: 0 };
 
var svg = d3.select("svg");
var width = svg.attr("width");
var height = svg.attr("height");
 
var g = svg.append("g").
attr("transform", "translate(" + marge.top + "," + marge.left + ")");
 
 
let hierarchyData = d3.hierarchy(dataset)
// .sum(function (d) {
//   return d.name;
// });
let tree = d3.tree().
size([width - 100, height - 100])
.
separation(function (a, b) {
  return a.parent == b.parent ? 1 : 2;
});
 
let treeData = tree(hierarchyData);
console.log(treeData)
let nodes = treeData.descendants().map(item => {
  // item.show = false;
  return item;
});
let links = treeData.links();
let beziler_generator = d3.linkHorizontal().
x(function (d,i) {
  return d.x;
}).
y(function (d) {
  return d.y;
});
// 边
g.append('g').
selectAll('path').
data(links).
enter().
append('path').
attr('d', function (d, i) {
  var start = { x: d.source.x, y: d.source.y };
  var end = { x: d.target.x, y: d.target.y };
  return beziler_generator({ source: start, target: end });
}).
attr('fill', 'none').
attr('stroke', 'blue').
attr('stroke-width', '1');
 
let gs = g.append('g').
selectAll('g').
data(nodes).
enter().
append('g').
attr('transform', function (d) {
  return 'translate(' + d.x + ',' + d.y + ')';
}).
attr('cursor', 'pointer')

// .
// on('mouseover', function (d, i, context) {
//   console.log(this);
//   d3.select(this).select('.detail').style('display', 'block');
// }).
// on('mouseout', function () {
//   d3.select(this).select('.detail').style('display', 'none');
// });
 
// gs.append('text').
// attr('x', function (d) {
//   return 30 - d.data.name.length * 8;
// }).
// text(function (d) {
//   return d.data.name;
// }).
// attr('class', 'detail').
// attr('style', function (d) {
//   return d.show ? 'display:block' : 'display:none';
// });
 
gs.append('circle').
attr('r', 4).
attr('fill', 'white').
attr('stroke', 'blue').
attr('stroke-width', 1)
.attr('x', function (d) {
  return d.x+100;
});
 
gs.append('text').
attr('x', function (d) {
  return -d.data.name.length * 8;
}).
attr('y', function (d) {
  return d.children ? -10 : 20;
}).
text(function (d) {
  return d.data.name;
});
 
// let zoom = d3.zoom().scaleExtent([1, 5])
//	.extent([[0, 0], [width, height]]).on('zoom', zoomed);
// zoom(svg);
//  
// function zoomed(d, i, context) {
//   g.attr('transform', d3.zoomTransform(this));
//   // svg.call(zoom.transform, d3.zoomTransform(this))
// }
 
console.log(1, treeData, nodes, links);
   
    </script>
</body>
</html>

# pack图

<!DOCTYPE html>
<meta charset="utf-8">
<style>

/*    circle {
        fill: rgb(31, 119, 180);
        fill-opacity: .25;
        stroke: rgb(31, 119, 180);
        stroke-width: 1px;
    } */

   /* .leaf circle {
        fill: #ff7f0e;
        fill-opacity: 1;
    } */

    text {
        font: 10px sans-serif;
        text-anchor: middle;
    }

</style>
<svg width="500" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var data={
"name":"gen",
"children":[
{
	"name":"num1",
	"children":[{"name":"num1-1","size":15},{"name":"num1-2","size":"5"}]
},
{
	"name":"num2",
	"children":[{"name":"num2-1","size":4},{"name":"num2-2","size":7},
			{"name":"num2-3","size":2},{"name":"num2-4","size":5}
	]
},
{
	"name":"num3",
	"size":10
},
{
	"name":"num4",
	"size":10
},
{
	"name":"num5",
	"size":10
}
]
};
    // 定义一个svg画布
    var svg = d3.select("svg"),
        // 以svg画布的宽度来作为直径的长度
        diameter = +svg.attr("width"),
        // 定义一个组元素,并将其移动定位
        g = svg.append("g").attr("transform", "translate(2,2)"),
        // 定义一个格式化函数,该格式化函数将返回参数的整数部分
        format = d3.format(",d");
	var colors = d3.scaleOrdinal(d3.schemeCategory10)
		

    // 创建一个包布局,返回包布局函数pack()
    var pack = d3.pack()

        // 设置包布局的宽、高尺寸
        .size([diameter - 4, diameter - 4]);

        // d3.hierarchy函数用来从层次型的数据构造根节点root及其递归的下属节点,计算并为每个节点添加
        // depth,height,parent,value属性
       var root = d3.hierarchy(data)

            // 对每一个父节点来说,将其所有子节点的size属性的值相加,作为该父节点的value的值,
			//叶子节点的size值作为其value值
            .sum(function(d) { return d.size; })

            // 对节点按照value属性值进行排序
            .sort(function(a, b) { return b.value - a.value; });

        // 定义节点元素
        var node = g.selectAll(".node")

            // pack(root)函数为root节点及其递归的下属节点计算并添加r,x,y属性,
			//r用来确定节点半径的大小,x,y用来确定节点的位置
            // desentdants()函数返回树形结构的数据中的所有节点组成的数组
            // 此处为节点绑定数据
            .data(pack(root).descendants())
            .enter().append("g")

            // 父节点和叶子节点的样式设定
            .attr("class", function(d) { return d.children ? "node" : "leaf node"; })

            // 根据节点的x,y来确定其摆放的位置
            .attr("transform", function(d) { 
				return "translate(" + d.x + "," + d.y + ")"; 
			});

        // 为节点添加title属性,即鼠标悬浮显示的信息
        node.append("title")
            .text(function(d) { return d.data.name + "\n" + format(d.value); });

        // 根据节点的r属性值来绘制代表节点的圆
        node.append("circle")
            .attr("r", function(d) { 
				console.log(d)
				return d.r; 
			}).attr("fill",(d)=>{
				if(d.parent){
					return colors(d.parent.data.name)
				}else{
					return colors("xxx")
				}
			}
			
			
			)

        // 若为叶子节点,则添加文字标签
        node.filter(function(d) { return !d.children; }).append("text")
            .attr("dy", "0.3em")
            .text(function(d) { return d.data.name.substring(0, d.r / 3); });
   

</script>

# 总结

  • d3.pack()创建打包图格式和大小
  • d3.hierarchy() 层级
  • pack(root).descendants()得出的数据结构如上图所示x、y、r参数
最后更新: 11/8/2019, 11:22:15 AM