数据可视化--D3.js入门(数据集与数据)

本文详细介绍了D3.js的基础知识,包括数据驱动文档的概念、选择集的操作、数据绑定、数组、映射、集合和嵌套结构的使用。重点讲解了如何利用D3.js创建条形图,涵盖了select()、selectAll()、datum()、data()等核心函数,并提供了实际的代码示例。此外,还讨论了数据排序、数组操作和集合管理,为D3.js的数据可视化实践打下坚实基础。
摘要由CSDN通过智能技术生成

D3(Data-Driven Document):数据驱动文档

D3是一个JavaScript的数据库,是用来做数据可视化的。其中文档指的是DOM,即文档对象模型(Document Object Model)。D3允许用户绑定任意数据到DOM,然后根据数据来操作文档,创建可交互式图表。

D3的优势:

  1. 数据能够与DOM绑定在一起 ,使数据和图形成为一个整体。
  2. 数据转换和绘制是独立的
  3. 代码简洁
  4. 大量布局
  5. 基于SVG,缩放不会损失精度

学习D3.js之前需要学习的:

  1. HTML/HTML5基础
  2. CSS/CSS3基础
  3. JavaScript基础
  4. DOM基础
  5. SVG基础

学习D3.js的网站:

D3的官网,含有API和大量示例:http://d3js.org/
D3创始人制作的,有很多说明文档:https://www.dashingd3js.com/
使用d3是需要引用:

<script type="text/javascript" src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>

第一节:数据集与数据

选择集:select()、selectAll()

选择集:d3.select、d3.selectAll返回的对象称为选择集(selection),添加、删除、设定网页中的元素,都得使用选择集。

  1. select() :返回匹配选择器的第一个元素。
  2. selectAll(): 返回匹配选择器的所有元素。

以下是关于它们的例子:

选择元素:

//使用CSS选择器
	d3.select("body");//直接选择元素
	d3.select("#part1");//选择id为part1的元素
	d3.select(".part2");//选择class为part2的元素(多个中的第一个)
	d3.selectAll(".part2");//选择class为part2的所有元素
	d3.selectAll("ul li");//选择ul中所有的li元素
//使用DOM API(不建议使用,建议直接使用上面那种)
	var x=document.getElementById("part1");//getElementByClassName(用selectAll())、getElementByTagName...
	d3.select(x);//选择id为part1的元素
//选择元素需要进行选择==>“连缀语法”。
	d3.select("body")
	  .selectAll("p");//选择body下的所有p元素
  1. 查看选择集状态:
    selection.empty():如果选择集为空,则返回true;如果不为空,返回false。
    selection.node():返回第一个非空元素,如果选择集为空,返回null。
    selection.size():返回选择集中的元素个数
  2. 设置和获得属性:
    ①设置和获得属性: .append()生成标签、.attr()生成属性。
    <1>设置标签:selection.append(“标签名”);
    <2>设置属性:selection.attr(“name”,“value”);//name属性名称、value属性值
    获得属性:selection.attr(“name”);
		var svg=d3.select("body")  //选择元素body
				  .append("svg")	//生成svg标签
				  .attr("width",width) //生成width属性
				  .attr("height",height);

②设值和获取class(CSS类):
<1>设置class:selection.classed(“name”,“value”);//name类名、value布尔值,表示类是否开启。
<2>获得class:selection.classed(“name”);
注:.attr()也可以设置类,但设置多个类不方便:d3.select(“p”).attr(“class”,“part1 part2”);//类名间用空格隔开

	d3.select("p")
	  .classed("part1",true)//开启part1类,会在元素标签添加class="part1"。
	  .classed("part2",false);//不开启part2类

③设置或获取选择集的样式style:
<1>设置style:selection.style(“name”,“value”);//name样式名,value样式值
<2>获得style:selection.style(“name”);

	d3.select("p")
	  .style("color","red");
	  .style("font-size","30px");

④(有些属性不能通过.attr()添加:比如文本输入中的value)设置或获取选择集的属性:
<1>设置属性:selection.property(“name”,“value”);//name属性名,value属性值
<2>获得属性:selection.property(“name”);

//html代码
<input id="part1" type="text" name="part1" />//设置value属性
//script代码
	d3.select("#part1")
	  .property("value","输入");

⑤设置或获得文本内容:
<1>设置文本内容:selection.text(“value”);
相当于DOM中的innerHTML替换标签文本,不包括文本中的标签内容
<2>获得文本内容:selection.text();

//html代码
<p>This<span>is</span>a paragraph</p>
//script代码
	d3.select("body")  //选择元素body
	  .selectAll("p")  //选择所有元素p
	  .text(); 

	//输出:This is a paragraph 

⑥设置或获得选择集的内部HTML内容:
<1>设置HTML内容:selection.html(“value”);
相当于DOM中的innerHTML替换标签文本,包括文本中的标签内容
<2>获得HTML内容:selection.html();

//html代码
<p>This<span>is</span>a paragraph</p>
//script代码
	d3.select("body")  //选择元素body
	  .selectAll("p")  //选择所有元素p
	  .html(); 

	 // 输出:This<span>is</span>a paragraph
  1. 选择集的添加、插入、删除操作:
    ①添加selection.append(“name”);//在末尾添加标签名为name
    ②插入selection.insert(“name”,“before”);//插入标签name,在before标签之前
    ③删除selection.remove();//删除某标签内容
//HTML代码
		<p>Car</p>
		<p id="plane">Plane</p>
		<p>Ship</p>
//script代码
		var body=d3.select("body");//选择body元素
		body.append("p")
			.text("Train");//在body中所有元素的末尾添加一个p元素,内容为Train

		body.insert("p","#plane")
			.text("Bike");//在body中id为plane的元素前添加p元素,内容为Bike

		var plane=d3.select("#plane");
		plane.remove();//删除id为plane的元素 

数据绑定:datum()、data()

数据绑定:使用选择元素里“含有”数据。
绑定的顺序:默认,data()是按索引号顺序绑定。可以不按顺序进行,使用key键函数(只有在原选择集已经绑定有数据的情况下,使用键函数才有效果)。

  1. selection.datum(“value”):选择集中的每个元素绑定相同的数据value。
//.datum()用法:
	var p=d3.select("body")
			.selectAll("p");

			p.datum("Animal")//绑定字符串Animal到选择集上
			 .append("span")//在每个p元素后创建一个span元素,在被绑定数据的选择集中添加元素后,新元素会继承改数据。
			 .text(function (d,i) {//定义一个无名函数,d代表被绑定的字符串,i代表索引号(可以改变字母但意思不变)
			 	return d+" "+i;
			 });

			console.log(p);//查看选择集p,含有属性__data__。子元素span继承该属性。
  1. selection.data(“values”,key):选择集每一个元素分别绑定values的每一项,key是一个键函数,用于指定绑定数组时的对应规则。
//.data()用法:
	var dataset=[3,6,9,12,15];//定义数组
	var p=d3.select("body").selectAll("p");
	var update=p.data(dataset);//绑定数据到选择集
	console.log(update);//输出绑定的结果
	console.log(update.enter());
	console.log(update.exit());
	
	//update:数组长度=元素数量(绑定的数据的元素,即将被更新)
	//enter:数组长度>元素数量(部分还不存在的元素,即将进入可视化)
	//exit:数组长度<元素数量(多余的元素,即将退出可视化)
	//绑定顺序
	var persons=[{id:3,name:"张三"},
					 {id:6,name:"李四"},
					 {id:9,name:"王五"}];

		var p=d3.select("body")
				.selectAll("p");

			//绑定数据,并修改p元素的内容
			p.data(persons)
			 .text(function(d){
			 	return d.id+":"+d.name;
			 })

			 // 输出:3:张三
				//   6:李四
				//   9:王五

			//更新persons里面的数据
			persons=[{id:6,name:"张三"},
					 {id:9,name:"李四"},
					 {id:3,name:"王五"}];
			//根据键函数规则绑定数据,并修改数据
			p.data(persons,function(d){return d.id;})//使用id作为键
			 .text(function(d){
			 	return d.id+":"+d.name;
			 })

			 //输出顺序不按索引顺序绑定,而是按照键值依次对应
			  // 输出:3:王五
				//   6:张三
				//   9:李四

①enter(存在多余数据)的处理方法:append()添加元素后修改内容

//例子:p不为空集
	var dataset=[3,6,9,12,15];//定义数组,设p元素少于5个
	var p=d3.select("body")
			.selectAll("p");

	//绑定数据后获得update和enter部分
	var update=p.data(dataset);//绑定数据到选择集
	var enter=update.enter();

	//update部分的处理方法是直接修改内容
	update.text(function (d) { return d;});
	//enter部分的处理方法是添加元素后在修改内容
	enter.append("p")
		 .text(function(d){ return d;});
//例子:p为空集
	var dataset=[10,20,30,40,50];//定义数组
	var body=d3.select("body");
	body.selectAll("p") //没有p元素,则选中一个空集
		.data(dataset)
		.enter()
		.append("p")
		.text(function(d){ return d;});

②exit(存在多余元素)的处理方法:remove()删除元素

	var dataset=[10,20,30];
	var p=d3.select("body")
			.selectAll("p");

	//绑定数据后,分别获取update和exit部分
	var update=p.data(dataset);
	var exit=update.exit();

	//update部分的处理方法是修改内容
	update.text( function(d){ return d});

	//exit部分的处理方法是删除
	exit.remove();

注:无论是什么情况都可以使用此处理模板:

//处理模板:											
	var dataset=[10,20,30];							
	var p=d3.select("body")							
			.selectAll("p");						
													
	//绑定数据后返回update、enter和exit部分			
	var update=p.data(dataset);						
	var enter=update.enter();						
	var exit=update.exit();							
													
	//update部分的处理方法是直接修改内容				
	update.text( function(d){ return d});			
													
	//enter部分的处理方法是添加元素后在修改内容			
	enter.append("p")								
		 .text(function(d){ return d;});			
													
	//exit部分的处理方法是删除						
	exit.remove();									

③过滤器(filter):根据被绑定数据对某选择集的元素进行过滤。

selection.filter(function(d,i){
	if(d>20)
		return true;
	else
		return false;
	});

④选择集顺序sort():可以根据被绑定数据重新排列选择集中的元素。
注:sort()的参数是一个无名函数,该函数也称为比较器

	selection.sort(function(a,b){return b-a;});//递减顺序
	selection.sort(function(a,b){return a-b;});//递增顺序

⑤each():允许对选择集的各元素分别处理。

	var persons=[{id:1001,name:"zhangsan"},
				 {id:1002,name:"lisi"}];

	var p=d3.select("body")
			.selectAll("p");

		p.data(persons)
		 .each(function(d,i){ //被绑定数据里没有age属性,通过each()函数为每一项添加了age属性
		 	d.age=20;
		 })
		 .text(function(d,i){
		 	return d.id+" "+d.name+" "+d.age;
		 });

⑥call():允许将选择集自身作为参数,传递给某一个函数

d3.selectAll("div").call(myfun);//将选择集div传递给myfun函数	

数组Array:

数组:通常是由相同数据类型的项组成集合,拥有数组名,可以凭借数组名和下标来访问数据项。
①排序:对选择集使用sort()时,如果不指定比较函数,默认是d3.ascending。
有函数时,function(a,b),a位于b之前,则返回值小于0;a位于b之后,则返回值大于0;a与b相等,则返回值为0。
没有函数时,d3.ascending(a,b),递增函数。a<b,返回-1;a>b,返回1;a=b,返回0。d3.descending(a,b),递减函数。a>b,返回-1;a<b,返回1;a=b,返回0。

		var numbers=[54,23,77,11,34];
	 	numbers.sort(d3.ascending);
	 	console.log(numbers); // [11,23,34,54,77]

②求值:求取数组的最大值、最小值、中间值、平均值等。
accessor为可选函数,即可以在求值时调用函数。
<1>d3.min(array[])、d3.min(array[],accessor):返回数组最大值
<2>d3.max(array[])、d3.max(array[],accessor):返回数组最小值
<3>d3.extend(array[])、d3.extend(array[],accessor):返回数组最小值和最大值

//例子:min、max、extend

	//数组定义
	var numbers=[30,20,10,50,40];

	//求最小值和最大值
	var min=d3.min(numbers);
	var max=d3.max(numbers);
	var extent=d3.extent(numbers);

	//输出结果
	console.log(min);//10
	console.log(max);//50
	console.log(extent);//[10,50]

	//使用accessor,在求值前先处理数据
	//numbers数组的每一项都会调用此函数。
	var minAcc=d3.min(numbers,function(d){return d*3;});
	//numbers的每一项*3==>[90,60,30,150,120]==>再取最小值
	var maxAcc=d3.max(numbers,function(d){return d-5;});
	var extendAcc=d3.extent(numbers,function(d){return d%7;});

	//输出结果
	console.log(minAcc);//30
	console.log(maxAcc);//45
	console.log(extendAcc);//[1,6]

<4>d3.sum(array[])、d3.sum(array[],accessor):返回数组总和,如果数组为空,则返回0
<5>d3.mean(array[])、d3.mean(array[],accessor):返回数组的平均值,如果数组为0,则返回0

//例子:sum、mean
		//数组定义,undefined和NaN不会影响
		var numbers=[69,11,undefined,53,27,82,65,34,NaN];
		//求总和、平均值
		var sum=d3.sum(numbers,function(d){return d/3;});
		var mean=d3.mean(numbers);
		//输出结果
		console.log(sum);//113.66666666666667
		console.log(mean);	//48.714285714285715

<6>d3.median(array[])、d3.median(array[],accessor):求数组的中间值,如果数组为空,则返回undefined

//例子:median直接忽略无效值
	var numbers1=[3,1,7,undefined,9,NaN];
	d3.median(numbers1);//返回5,偶数,返回中间两位相加除以2
	var numbers2=[3,1,7,undefined,9,10,NaN];
	d3.median(numbers2);//返回7,奇数,返回最中间的值

<7>d3.quantile(numbers,p):求取p分位点的值,p的范围[0,1]。(数组需先递增排序)

//例子:quantile
	var numbers=[3,1,10];
	numbers.sort(d3.ascending);
	d3.quantile(numbers,0);//返回1
	d3.quantile(numbers,0.25);//返回2
	d3.quantile(numbers,0.5);//返回3
	d3.quantile(numbers,0.75);//返回6.5
	d3.quantile(numbers,1.0);//返回10

	//简化:d3.quantile(numbers.sort(d3.ascending),0.5);

<8>d3.variance(array[])、d3.variance(array[],accessor):求方差

<9>d3.deviation(array[])、d3.deviation(array[],accessor):求标准差

<10>d3.bisectLeft():获取数组项左边位置
d3.bisect()、d3.bisectRight():获取数组项右边的位置
与JavaScript中的splice()函数一起使用:splice(3,1,“China”,“Japan”);//删除索引为3的一个元素,再插入两个元素

//例子:bisect、bisectLeft
	var numbers=[10,13,16,19,22,25];
	//iLeft的值为2
	var iLeft=d3.bisectLeft(numbers.sort(d3.accending),16);//16的左边位置

	//在iLeft位置处,删除0个项后,插入77
	numbers.splice(iLeft,0,77);

	console.log(numbers);//输出[10,13,77,16,19,22,25]

<11>d3.shuffle(array[]):将数组重新排列

//例子:shuffle
	var numbers=[10,13,16,19,22,25]
	d3.shuffle(numbers);

	console.log(numbers);//结果随机

<12>d3.merge(array[]):合并两个数组

//例子:merge
	d3.merge([[1],[2,3]]);//合并两个数组

<13>d3.pairs(array[]):返回邻接的数组对。以i项和i-1项为对返回。

//例子:pairs
	var colors=["red","blue","yellow"];
	var pairs=d3.pairs(colors);
	console.log(paris);//结果为[["red","blue"],["blue","yellow"]]

<14>d3.range([start],[stop],[step]):返回等差数列。stop为正,则最后的值小于stop;stop为负,则最后的值大于stop。start和step如果省略,则默认分别为0和1。

//例子:range
	var c=d3.range(2,10,2);//从2开始到10结束,不包括10,等差值为2。
	console.log(c);//输出[2,4,6,8]

<15>d3.permute(array,indexes):根据指定的索引号数组返回排列后的数组。

//例子:permute
	var animals=["cat","dog","bird"];

	var newAnimals=d3.permute(animals,[2,1,0]);//根据索引号[2,1,0]重新排序animals

	console.log(newAnimals);//输出:["bird","dog","cat"]

<16>d3.zip(arrays…):用多个数组来制作数组的数组。

//例子:zip

	var zip=d3.zip([1000,1001,1002],["zhangsan","lisi","wangwu"],[true,false,true]);//制作新的数组

	console.log(zip);  //输出:[[1000,"zhangsan",true],[1001,"lisi",false],[1002,"wangwu",true]]

<17>d3.transpose(matrix):求转置矩阵。

//例子:transpose
	var a=[[1,2,3],[4,5,6]];
	var t=d3.transpose(a);//转置矩阵
	console.log(t);//输出:[[1,4],[2,5],[3,6]]

映射Map:

映射Map:一种数据结构,由一系列键(key)和值(value)组成。每个key对应一个value,根据key可以获取和设定value,也可以根据key来查询value。

<1>d3.map([object],[key]):构建映射。object源数组,key用于指定映射的key

<2>map.has(key):如果指定的key存在,则返回true;反之,则返回false。

<3>map.get(key):如果指定的key存在,则返回key的value;否则,返回undefined。

<4>map.set(key,value):对指定的key设定value,如果该key已经存在,则新的value会覆盖旧的;如果不存在,则添加一个新的value。

<5>map.remove(key):如果指定key存在,则将此key和value删除,并返回true;如果不存在,返回false。

<6>map.keys():以数组形式返回该map的所有key。

<7>map.values():以数组形式返回该map的所有value。

<8>map.entries():以数组形式返回该map的所有key和value。

<9>map.forEach(function):分别对该映射中的每一项调用function函数,function函数传入两个参数:key、value。分别代表每一项的key和value。

<10>map.empty():如果该映射为空,返回true;否则,返回false。

<11>map.size():返回该映射的大小

var dataset=[{id:1000,color:"red"},
				 {id:1001,color:"green"},
				 {id:1002,color:"blue"}]

	//以数组dataset构成映射,并以其中各项的id作为键
	var map=d3.map(dataset,function(d){return d.id;});

	map.has(1001);//返回true
	map.has(1003);//返回false

	map.get(1001);//返回{id:1001,color:"green"}
	map.get(1003);//返回undefined

	//将1001键的值设置为{ id:1001,color:"yellow"}
	map.set(1001,{id:1001,color:"yellow"});

	//将1003键的值设置为{id:1003,color:"white"}
	map.set(1003,{id:1003,color:"white"})

	map.remove(1001);//删除键为1001的键和值

	map.keys();//返回["1000","1002","1003"]
	map.values();//返回所有的值
	map.entries();//返回所有的键和值

	//该循环会进行三次,键依次为1000、1002、1003
	map.forEach(function(key,value){
		console.log(key);
		console.log(value);
	});

	map.empty();//返回false
	map.size();//返回3

集合Set:

集合Set:表示具有特定性质的事物的总体。集合里的项叫做元素。
<1>d3.set([array]):使用数组构建集合,如果数组里有重复的元素,则只添加其中一项。

<2>set.has(value):如果集合中有指定元素,则返回true;如果没有,返回false。

<3>set.add(value):如果该集合中没有指定元素,则将其添加到集合中,并返回该元素;如果有,则不添加。

<4>set.remove(value):如果该集合中有指定元素,则将其删除并返回true;否则,返回false。

<5>set.values:以数组形式返回该集合中所有元素。

<6>set.forEach(function):对每个元素都调用function函数,函数里传入一个参数,即该元素的值。

<7>set.empty():如果该集合为空,则返回true;否则,返回false。

<8>set.size():返回该集合的大小。

	//源数组
	var dataset=[{"tiger","dragon","snake","horse","sheep"}];

	//构建一个集合,将其保存在变量set中
	var set=d3.set(dataset);

	set.has("tiger");//返回true
	set.add("monkey");//添加monkey,并返回monkey

	set.remove("snake");//删除snake

	set.values();//返回["tiger","dragon","horse","sheep","monkey"]

	set.forEach(function(value){console.log(value);});//集合中的每一个元素都调用function函数,该函数的内容为输出各元素。

	set.empty();//返回false
	set.size();//返回5//源数组
	var dataset=[{"tiger","dragon","snake","horse","sheep"}];

	//构建一个集合,将其保存在变量set中
	var set=d3.set(dataset);

	set.has("tiger");//返回true
	set.add("monkey");//添加monkey,并返回monkey

	set.remove("snake");//删除snake

	set.values();//返回["tiger","dragon","horse","sheep","monkey"]

	set.forEach(function(value){console.log(value);});//集合中的每一个元素都调用function函数,该函数的内容为输出各元素。

	set.empty();//返回false
	set.size();//返回5

嵌套结构Nest:

嵌套结构(Nest):能够使用键(key)对数组中的大量对象进行分类,多个键一层套一层,使得分类越来越具体,索引越来越方便。
<1>d3.nest():该函数没有任何参数,表示接下来将会构建一个新的嵌套结构。其他函数和它一起使用。

<2>nest.key(function):指定嵌套结构的键

<3>nest.entries(array):指定数组array将被用于构建嵌套结构的键。

//例子:key、entries
	var persons=[{id:100,name:"zhangsan",year:1989,hometown:"beijing"},
				 {id:101,name:"lisi",year:1987,hometown:"beijing"},
				 {id:102,name:"wangwu",year:1988,hometown:"shanghai"},
				 {id:103,name:"zhaoliu",year:1987,hometown:"guangzhou"},
				 {id:104,name:"sunqi",year:1989,hometown:"shanghai"}];

	var nest=d3.nest()
				//将year作为第一个键
			   .key(function(d){return d.year;})
			   //将hometown作为第二个键
			   .key(function(d){return d.homeown;})
			   //指定将应用嵌套结构的数组为persons
			   .entries(persons);
	console.log(nest);

<4>nest.sortKeys(comparator):按照键对嵌套结构进行排序,接在nest.key()后使用。

// 例子:sortkeys
	
	d3.nest()
	  .key(function(d){return d.year;})
	  .sortKeys(d3.descending)//按照键year进行排序
	  .key()//其他键的定义

<5>nest.sortValues(comparator):按照值对嵌套结构进行排序。

// 例子:sorValues
	var persons=[{sex:"男",age:48,name:"zhangsan"},
				 {sex:"男",age:42,name:"lisi"},
				 {sex:"男",age:45,name:"wangwu"},
				 {sex:"女",age:33,name:"zhaoliu"},
				 {sex:"女",age:31,name:"sunqi"}];

	var nest=d3.nest()
			   .key(function(d){return d.sex;})
			   .sortValues(function(a,b){
					return d3.ascending(a.age,b.age);
			   })
			   .entries(persons);

//	输出:[{key:"男",values:[
//				{sex:"男",age:42,name:"lisi"},
//				{sex:"男",age:45,name:"wangwu"},
//				{sex:"男",age:48,name:"zhangsan"}
//			]},
//		   {key:"女",values:[
//		   		{sex:"女",age:31,name:"sunqi"},
//		   		{sex:"女",age:33,name:"zhaoliu"}
//		   	]}]

<6>nest.rollup(function):对每一组叶子节点调用指定的函数function,该函数含有一个参数values,是当前叶子节点的数组。

// 例子:rollup
	var nest=d3.nest()
			   .key(function(d){return d.sex;})
			   .rollup(function(values){return values.length;})
			   .entries(persons);

//	输出:[{key:"男",value:3},
//		   {key:"女",value:2}]

<7>nest.map([array],“mapType”):以映射的形式输出数组。

//例子:map
	var map=d3.nest()
			  .key(function(d){return d.sex;})
			  .map(persons,d3.map);

//	输出:{
//			"女":[
//				{sex:"女",age:33,name:"zhaoliu"},
//				{sex:"女",age:31,name:"sunqi"}
//			],
//			"男":[
//				{sex:"男",age:48,name:"zhangsan"},
//				{sex:"男",age:42,name:"lisi"},
//				{sex:"男",age:45,name:"wangwu"}
//			]
//	}

:使用映射的方式输出时,其结果最外层是一个花括号,而不是中括号。即它是一个对象,而不是一个数组。内部的形式也有很多不同之处,请注意区别。

练习:制作一个Bar Chart

//html代码
<button type="button" onclick="mysort()">排序</button>
<button type="button" onclick="myadd()">增加数据</button>
//script代码
		//柱状图制作:矩形、坐标轴和文字
		//dataset定义柱状图中矩形长短
		var dataset=[50,43,120,87,99,167,142];
		
		var width=400;//SVG绘制区域的宽度
		var height=400;//SVG绘制区域的高度

		var svg=d3.select("body")//选择<body>
				  .append("svg")//在<body>中添加<svg>
				  .attr("width",width)//设定<svg>的宽度属性
				  .attr("height",height);//设定<svg>的高度属性

		var padding={top:20,right:20,bottom:20,left:20};//定义上下左右边框
		var rectStep=35;//矩形所占的宽度(包括空白),单位像素
		var rectWidth=30;//矩形所占的宽度(不包括空白),单位像素

		var rect=svg.selectAll("rect")
					.data(dataset)//绑定数据
					.enter()//获得enter部分
					.append("rect")//添加rect元素,使其与绑定数组的长度一致
					.attr("fill","black")//设置颜色为steelblue
					.attr("x",function(d,i){//设置矩形的x坐标
						return padding.left+i*rectStep;
					})
					.attr("y",function(d){//设置矩形的y坐标
						return height-padding.bottom-d;
					})
					.attr("width",rectWidth)//设置矩形的宽度
					.attr("height",function(d){//设置矩形的高度
						return d;
					});

		var text=svg.selectAll("text")
					.data(dataset)
					.enter()
					.append("text")
					.attr("fill","white")
					.attr("font-size","14px")
					.attr("text-anchor","middle")
					.attr("x",function(d,i){
						return padding.left+i*rectStep;
					})
					.attr("y",function(d){
						return height-padding.bottom-d;
					})
					.attr("dx",rectWidth/2)
					.attr("dy","1em")
					.text(function(d){
						return d;
					});

		//更新数据

		function draw(){
			//获取矩形的update部分
			var updateRect=svg.selectAll("rect")
							  .data(dataset);
			//获取矩形的enter部分
			var enterRect=updateRect.enter();
			//获取矩形的exit部分
			var exitRect=updateRect.exit();
			//矩形的update部分的处理方法:直接修改内容
			updateRect.attr("fill","black")
					  .attr("x", function(d,i){
					    return padding.left+i*rectStep;
					  })
					  .attr("y",function(d){
					  	return height-padding.bottom-d;
					  })
					  .attr("width",rectWidth)
					  .attr("height",function(d){
					  	return d;
					  });
			//矩形的enter部分的处理方法:添加元素后修改内容
			enterRect.append("rect")							
			 		 .attr("fill","black")
			 		 .attr("x", function(d,i){
					    return padding.left+i*rectStep;
					  })
					  .attr("y",function(d){
					  	return height-padding.bottom-d;
					  })
					  .attr("width",rectWidth)
					  .attr("height",function(d){
					  	return d;
					  });
			//矩形的exit部分的处理方法:删除
			exitRect.remove();	

			var updateText=svg.selectAll("text")
							  .data(dataset);
			var enterText=updateText.enter();
			var exitText=updateText.exit();

			updateText.attr("fill","white")
					  .attr("font-size","14px")
					  .attr("text-anchor","middle")
					  .attr("x",function(d,i){
							return padding.left+i*rectStep;
						})
					  .attr("y",function(d){
							return height-padding.bottom-d;
						})
					  .attr("dx",rectWidth/2)
					  .attr("dy","1em")
					  .text(function(d){
							return d;
						});

			enterText.append("text")
					 .attr("fill","white")
					 .attr("font-size","14px")
					 .attr("text-anchor","middle")
					 .attr("x",function(d,i){
							return padding.left+i*rectStep;
						})
					 .attr("y",function(d){
							return height-padding.bottom-d;
						})
					 .attr("dx",rectWidth/2)
					 .attr("dy","1em")
					 .text(function(d){
							return d;
						});

			exitText.remove();

		}

		function mysort(){
			dataset.sort(d3.ascending);//排序
			draw();
		}

		function myadd(){
			dataset.push(Math.floor(Math.random()*100));//添加一个项
			draw();
		}

转载于图书:《精通D3.js:交互式数据可视化高级编程》吕之华 著

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值