当前位置:   article > 正文

D3.js知识总结

d3.js

D3.js使用总结

D3.js官网

D3js 是一个可以基于数据来操作文档的 JavaScript 库。可以帮助你使用 HTML, CSS, SVG 以及 Canvas 来展示数据。D3 遵循现有的 Web 标准,可以不需要其他任何框架独立运行在现代浏览器中,它结合强大的可视化组件来驱动 DOM 操作。

D3设置SVG中的属性

  • 常见的属性

    id,class(特殊的属性)

    x,y,cx,cy(注意屏幕的坐标系)

    fill(填充的颜色),stroke(外轮廓的颜色)

    height,width(矩形的宽高),r(圆的半径)

    transform -> translate,rotate,scale(平移,旋转,缩放)

  • 设置元素的属性:element.attr(‘attr_name’,‘attr_value’)

    rect1.attr(‘y’,‘100’)

    d3.select(’#rect1’).attr(‘y’,‘100’)

使用D3添加&删除SVG元素

  • element.append()
const myRect = svg.append('rect');
const myRect = d3.select('#mainsvg').append('rect').attr('x','100')
  • 1
  • 2

​ 链式调用

  • element.remove()

    移除整个标签

数据绑定

  1. datum():绑定一个数据到选择集上
  2. data():绑定一个数组到选择集上,数组的各项值分别与选择集的各元素绑定。(更常用)

插入&删除元素

  1. append():在选择集末尾插入元素
  2. insert():在选择集前面插入元素
  3. remove():删除一个元素
  4. enter()方法,使得在有数据,而没有足够图形元素的情况下,补充足够的元素

比例尺的使用

线性比例尺

domain域和range域都可以连续变化

<body>
    <script>
    	var dataset = [1.2, 2.3, 0.9, 1.5, 3.3];
    	var min = d3.min(dataset);//得到最小值
    	var max = d3.max(dataset);//得到最大值
    	var scaleLinear = d3.scaleLinear()
    		.domain([min,max])
    		.range([0,300]);
    	document.write("scaleLinear(1)输出:"+scaleLinear(1));
    	d3.select("body").append("br");//换行
    	document.write("scaleLinear(2)输出:"+scaleLinear(2));
    	d3.select("body").append("br");
    	document.write("scaleLinear(3.3)输出:"+scaleLinear(3.3));
    </script>
  </body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

请添加图片描述

var scaleLinear = d3.scaleLinear()
.domain([min,max])
.range([0,300]);

由映射关系可以看出dataset数组中的[0.9,3.3]映射[0,300]

序数比例尺

domain域和range域是离散的,即数组

<body>
    <script>
    	var index = [0,1,2,3,4];
    	var color = ["red","blue","yellow","black","green"];
    	var scaleOrdinal = d3.scaleOrdinal()
    		.domain(index)
    		.range(color);
    	document.write("scaleOrdinal(1)输出:"+scaleOrdinal(1));
    	d3.select("body").append("br");//换行
    	document.write("scaleOrdinal(2)输出:"+scaleOrdinal(2));
    	d3.select("body").append("br");
    	document.write("scaleOrdinal(4)输出:"+scaleOrdinal(4));
    </script>
  </body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

请添加图片描述

var scaleOrdinal = d3.scaleOrdinal()
.domain(index)
.range(color);

index数组中的值与color数组中的字符是一一对应关系

坐标轴

  1. d3.axisTop():创建顶部坐标轴
  2. d3.axisRight():创建垂直右坐标轴
  3. d3.axisBottom():创建底部坐标轴
  4. d3.axisLeft():创建垂直居左坐标轴

定义一个坐标轴

//为坐标轴定义一个线性比例尺
    	var xScale = d3.scaleLinear()
    		.domain([0,d3.max(dataset)])
    		.range([0,250]);
    	//定义一个坐标轴
    	var xAxis = d3.axisBottom(xScale)//定义一个axis,由bottom可知,是朝下的
    	.ticks(7);//设置刻度数目
    	g.append("g")
    	.attr("transform","translate("+20+","+(dataset.length*rectHeight)+")")
    	.call(xAxis);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

实现动态的方法

  1. transition()

    用于启动过渡效果。其前后是图形变化前后的状态(形状、位置、颜色等)

  2. duration()

    用来指定过渡的持续时间,单位为毫秒

    .attr("fill","red") //初始颜色为红色
    .transition() //启动过渡
    .duration(1000) //设置过渡的持续时间为1秒
    .attr("fill","green") //终止颜色为绿色
    
    • 1
    • 2
    • 3
    • 4
  3. delay()

    指定延迟的时间,表示一定时间后才开始转变,单位同样为毫秒。此函数可以对整体指定延迟,也可以对个别指定延迟。

  4. ease()

    指定过渡的缓动函数。常用的有:

    d3.easeLinear:普通的线性变化

    d3.easeCircle:慢慢地到达变换地最终状态、

    d3.easeElastic:带有弹跳地到达最终状态

    d3.easeBounce:在最终状态处弹跳几次

    调用方式如 .ease(d3.easeLinear)

如何添加交互

var circle = svg.append("circle");
circle.on("click",function(){
	//在此处添加交互内容
});
  • 1
  • 2
  • 3
  • 4

在D3中,每一个选择集都有on()函数,用于添加事件监听器。

其中,on()的第一个参数是监听的事件,第二个参数是监听到时间后响应的内容,第二个参数是一个函数。

​ 对于鼠标,常用事件有:

click:鼠标单击某元素时,相当于mousedown和mouseup组合在一起

mouseover:光标放在某元素上

mouseout:光标从某元素上移出来时

mousemove:鼠标被移动的时候

mousedown:鼠标按钮被按下

mouseup:鼠标按钮被松开

dblclick:鼠标双击

键盘常用的事件

keydown:当用户按下任意键时触发,按住不放会重复触发此事件。

keypress:当用户按下字符键(大小写字母、数字、加号、等号、回车等)时触发,按住不放会重复触发此事件

keyup:当用户释放键时触发

触屏常用的事件

touchstart:当触摸点被放在触摸屏上时

touchmove:当触摸点在触摸屏上移动时

touchend:当触摸点从触摸屏上拿开时

实现一个简单图表

样例:

请添加图片描述

代码:

<!DOCTYPE html>
<html>
  <head>
    <title>testD3_chp6_1.html</title>
    <script type="text/javascript" src="http://d3js.org/d3.v5.min.js">
	</script>
    <meta name="keywords" content="keyword1,keyword2,keyword3">
    <meta name="description" content="this is my page">
    <meta name="content-type" content="text/html; charset=GBK">
  </head>
  
  <body>
    <svg width="960" height="600"></svg>
    <script>
    	var marge = {top:60,bottom:60,left:60,right:60}//设置边距
    	var dataset = [ 250 , 210 , 170 , 130 , 90 ];  //数据(表示矩形的宽度)
    	var svg = d3.select("svg");//得到svg画布
    	var g = svg.append("g")//定义一个用来装整个图表的一个分组,并设置他的位置
    		.attr("transform","translate("+marge.top+","+marge.left+")");
    	
    	var rectHeight = 30;//设置每一个矩形的高度
    	
    	g.selectAll("rect")
    		.data(dataset)
    		.enter()
    		.append("rect")
    		.attr("x",20)//设置左上点的x
    		.attr("y",function(d,i){//设置左上点的y
    			return i*rectHeight;
    		})
    		.attr("width",function(d){//设置宽
    			return d;
    		})
    		.attr("height",rectHeight-5)//设置长
    		.attr("fill","blue");//颜色填充
    </script>
  </body>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

力导向图

d3.forceSimulation() :新建一个力导向图

d3.forceSimulation().force():添加或者移除一个力

d3.forceSimulation().nodes():输入是一个数组,然后将这个输入的数组进行一定的数据转换,例如添加坐标什么的

d3.forceLink.links():这里输入的也是一个数组(边集),然后对输入的边集进行转换

tick函数:这个函数对于力导向图来说非常重要,因为力导向图是不断运动的,每一时刻都在发生更新,所以需要不断更新节点和连线的位置

d3.drag():是力导向图可以被拖动

力导向图绘制流程:

  1. 数据准备
var marge = {top:60,bottom:60,left:60,right:60}
    	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+")");
    		
    	//准备数据
    	var nodes = [//节点集
    		{name:"湖南邵阳"},
    		{name:"山东莱州"},
    		{name:"广东阳江"},
    		{name:"山东枣庄"},
    		{name:"泽"},
    		{name:"恒"},
    		{name:"鑫"},
    		{name:"明山"},
    		{name:"班长"}
    	];
    	
    	var edges = [//边集
    		{source:0,target:4,relation:"籍贯",value:1.3},
    		{source:4,target:5,relation:"舍友",value:1},
    		{source:4,target:6,relation:"舍友",value:1},
    		{source:4,target:7,relation:"舍友",value:1},
    		{source:1,target:6,relation:"籍贯",value:2},
    		{source:2,target:5,relation:"籍贯",value:0.9},
    		{source:3,target:7,relation:"籍贯",value:1},
    		{source:5,target:6,relation:"同学",value:1.6},
    		{source:6,target:7,relation:"朋友",value:0.7},
    		{source:6,target:8,relation:"职责",value:2}
    	];
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  1. 设置一个颜色比例尺
//设置一个color的颜色比例尺,为了让不同的扇形呈现不同的颜色
    	var colorScale = d3.scaleOrdinal()
    		.domain(d3.range(nodes.length))
    		.range(d3.schemeCategory10);
  • 1
  • 2
  • 3
  • 4
  1. 新建一个力导向图
var forceSimulation = d3.forceSimulation()
    		.force("link",d3.forceLink())
    		.force("charge",d3.forceManyBody())
    		.force("center",d3.forceCenter());
  • 1
  • 2
  • 3
  • 4
  1. 生成节点数据
//生成节点数据
    	forceSimulation.nodes(nodes)
    		.on("tick",ticked);//这个函数很重要,后面给出具体实现和说明
  • 1
  • 2
  • 3
  1. 生成边集数据
//生成边数据
    	forceSimulation.force("link")
    		.links(edges)
    		.distance(function(d){//每一边的长度
    			return d.value*100;
    		}) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  1. 设置图形中心位置
//设置图形的中心位置	
    	forceSimulation.force("center")
    		.x(width/2)
    		.y(height/2);
  • 1
  • 2
  • 3
  • 4
  1. 绘制边
//绘制边
    	var links = g.append("g")
    		.selectAll("line")
    		.data(edges)
    		.enter()
    		.append("line")
    		.attr("stroke",function(d,i){
    			return colorScale(i);
    		})
    		.attr("stroke-width",1);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  1. 边上的文字
var linksText = g.append("g")
    		.selectAll("text")
    		.data(edges)
    		.enter()
    		.append("text")
    		.text(function(d){
    			return d.relation;
    		})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  1. 老规矩,先建立用来放在每个节点和对应文字的分组
var gs = g.selectAll(".circleText")
    		.data(nodes)
    		.enter()
    		.append("g")
    		.attr("transform",function(d,i){
    			var cirX = d.x;
    			var cirY = d.y;
    			return "translate("+cirX+","+cirY+")";
    		})
    		.call(d3.drag()
    			.on("start",started)
    			.on("drag",dragged)
    			.on("end",ended)
    		);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. 节点和文字
//绘制节点
    	gs.append("circle")
    		.attr("r",10)
    		.attr("fill",function(d,i){
    			return colorScale(i);
    		})
    	//文字
    	gs.append("text")
    		.attr("x",-10)
    		.attr("y",-20)
    		.attr("dy",10)
    		.text(function(d){
    			return d.name;
    		})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  1. ticked函数的实现
function ticked(){
    		links
    			.attr("x1",function(d){return d.source.x;})
    			.attr("y1",function(d){return d.source.y;})
    			.attr("x2",function(d){return d.target.x;})
    			.attr("y2",function(d){return d.target.y;});
    			
    		linksText
    			.attr("x",function(d){
    			return (d.source.x+d.target.x)/2;
    		})
    		.attr("y",function(d){
    			return (d.source.y+d.target.y)/2;
    		});
    			
    		gs
    			.attr("transform",function(d) { return "translate(" + d.x + "," + d.y + ")"; });
    	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  1. drag
function started(d){
    		if(!d3.event.active){
    			forceSimulation.alphaTarget(0.8).restart();设置衰减系数,对节点位置移动过程的模拟,数值越高移动越快,数值范围[0,1]
    		}
    		d.fx = d.x;
    		d.fy = d.y;
    	}
    	function dragged(d){
    		d.fx = d3.event.x;
    		d.fy = d3.event.y;
    	}
    	function ended(d){
    		if(!d3.event.active){
    			forceSimulation.alphaTarget(0);
    		}
    		d.fx = null;
    		d.fy = null;
    	}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

具体细节可以参考官方文档:力导向图

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/529265
推荐阅读
相关标签
  

闽ICP备14008679号