标签:疑惑 ons divide move insert 的区别 nod 理解 pat
d3的介绍并且利用广泛实现的SVG、JavaScript和CSS标准
var body = d3.select("body"); //选择文档中的body元素
var p1 = body.select("p"); //选择body中的第一个p元素
var p = body.selectAll("p"); //选择body中的所有p元素
var svg = body.select("svg"); //选择body中的svg元素
var rects = svg.selectAll("rect"); //选择svg中所有的svg元素
说明:
1选择对象可以选择后来添加到页面的元素;
2可以连缀操作,连缀选择到谁,就是那些元素对象
3可以选择不存在的元素,但是必须使用append进行插入,返回的是插入元素的对象
绑定数据
选择集和绑定数据通常是一起使用的。
datum():绑定一个数据
到选择集上
data():绑定一个数组
到选择集上,数组的各项值分别与选择集的各元素绑定
datum使用:
假设现在有三个段落元素如下。
html
<p>Apple</p>
<p>Pear</p>
<p>Banana</p>
js代码
var str = "China";
var body = d3.select("body");
var p = body.selectAll("p");
p.datum(str);
p.text(function(d, i){
return "第 "+ i + " 个元素绑定的数据是 " + d;
});
结果
第 0 个元素绑定的数据是 China
第 1 个元素绑定的数据是 China
第 2 个元素绑定的数据是 China
总结:
d 代表数据,也就是与某元素绑定的数据。
i 代表索引,代表数据的索引号,从 0 开始。
data使用:
js代码
var dataset = ["I like dog","I like cat","I like snake"];
var body = d3.select("body");
var p = body.selectAll("p");p.data(dataset)
.text(function(d, i){
return d;
});
结果
I like dog
I like cat
I like snake
上述的数据都是和html是一一对应的,如果我的html元素和数据的个数不对应会怎么样呢。
d3.js中data(), enter() 和 exit()的作用
data()
先看一个例子:
<body>
<p></p>
<p></p>
<p></p>
</body>
执行代码:
d3.select("body").selectAll("p").data([1, 2, 3])
这里,data()是用来绑定数据到选择的DOM元素上.这样以后,就可以针对这些数据做一些相关操作,比如设置元素宽度等。
从表面上,并不能看出什么变化。但在内部,它是在对应的DOM元素上添加了一个data属性,可以通过document.getElementsByTagName("p")[0].data看到。
总结
data() 选择的是绑定元素和绑定数据一致的部分
enter()和exit()
在上面data()的例子中,我们的DOM元素和数据的个数是一样的。但如果不一样的话,我们该怎么办?
enter()和exit()就是用来处理这种情况的。
enter()
当DOM数量少于data的数量,或者压根一个都没有的时候,我们一般会希望让程序帮忙创建。
下面的例子,我们没有事先提供DOM元素:
<body>
</body>
仍旧执行:
d3.select("body").selectAll("p").data([1, 2, 3])
与上面例子不同的是,上面的例子中我们可以继续执行.style("width", "100px")等操作。但这里我们不能了,因为我们没有选择到DOM元素,需要先创建。
enter()是用来在绑定数据之后,选择缺少的那部分DOM元素
。我们可能会疑惑,既然是缺少的部分,怎么选择呢?这里就需要我们发挥一点想象力,想象我们选择了一些不存在的东西。我们可以称之为“虚拟DOM”或“占位符(placeholder)”。
enter()只是进行选择,并未实际添加所需DOM元素。因此在enter()之后一般都会配合append()来进行DOM元素的实际创建。
由此以来,我们使用 d3.select("body").selectAll("p").data([1,2,3]).enter().append("p") 即可根据数据自动创建所需的DOM元素。
exit()
与enter()相反,exit()是用来选择那些与数据相比多出来的DOM元素。
在下面例子中,我们多提供了一个DOM元素:
<body>
<p></p>
<p></p>
<p></p>
<p></p>
</body>
这回就容易理解了,因为是多出来的,那么就是实际存在的,即最后一个<p>。
多出来的话,我们可以接着用.remove()移除这些元素,代码如下:
d3.select("body").selectAll("p").data([1, 2, 3]).exit().remove();
元素常用的操作
以下可以获取也可以进行设置,设置的时候可以使用回调函数
selection.attr - 设置或获取指定属性。
selection.classed - 添加或删除选定元素的 CSS 类(CSS class)。
selection.style - 设置或删除 CSS 属性。style优先级高于attr。
selection.text - 设置或获取选定元素的标签体文本内容。
selection.html - 设置或获取选定元素的 HTML 内容(类似 innerHTML )
selection.append - 创建并添加新元素到选定元素后。
selection.insert - 创建并添加新元素到选定元素前。
selection.remove - 从当前文档对象中删除选定的元素。
路径生成器
在svg中的path 标签中的d属性需要放置路径,我们可以在d3中使用路径生成器生成path标签中的d属性的值
高版本使用的是: var liner = d3.line()
版本低的使用:var liner = d3.svg.line()
上面返回的是一个构造函数,该函数下有两个方法:
line.x - 设置或获取x轴访问器.
line.y - 设置或获取y轴访问器
使用方法如下:
//定义曲线生成器
var liner=d3.line() liner.x(function(data,index){ //data调用构造函数传入数组的每个值,index是索引 return data }).y(function(data,index){ //data调用构造函数传入数组的每个值,index是索引 return data }) //调用构造生成器 var data=[1,2,3,4] liner(data)
区域生成器
在svg中的path 标签中的d属性需要放置路径,我们可以在d3中使用路径生成器生成path标签中的d属性的值
高版本使用的是: var arear = d3.area()
低版本使用的是: var arear = d3.svg.area()
上面返回的是一个构造函数可以调用如下函数:
area.x - 获取或设置x坐标的访问器.
area.x0 - 获取或设置x0坐标(基线)的访问器.
area.x1 - 获取或设置x1坐标(背线)的访问器.
area.y - 获取或设置y坐标的访问器.
area.y0 - 获取或设置y0坐标(基线)的访问器.
area.y1 - 获取或设置y1坐标(背线)的访问器.
let area=d3.area() .x(function(data,i){ return scaleX(i) }) .y(function(data){ return scaleY(data) }) //生成面积 g.append("path") .attr("d",area(dataset)) .style("fill","blue")
比例尺
我们知道地图有比例尺,作为地图缩放时的标尺。
同样的D3也比例尺。
D3绘制表是需要依赖数据的,有时候数据可能太大或太小,太小的数据如果按照实际绘制导致看不见,太大的数据按照事迹绘制将会超出画布的范围。因此比例尺在D3绘制中是非常重要的。
比例尺分为线性比例尺和序数比例尺
线性比例尺:
能将一个连续的区间,映射到另一区间。要解决柱形图宽度的问题,就需要线性比例尺
例如:
现有一组数据:
var dataset = [1.2, 2.3, 0.9, 1.5, 3.3];
有如下要求:将 dataset 中最小的值,映射成 0;将最大的值,映射成 300。
代码如下:
var min = d3.min(dataset);
var max = d3.max(dataset);
//注意高版本的使用的是d3.scaleLiner(),低版本的使用的是d3.scale.linear()
//定义比例尺的构造函数var linear = d3.scaleLinear()
.domain([min, max])
.range([0, 300]);
//使用如下
linear(0.9); //返回 0
linear(2.3); //返回 175
linear(3.3); //返回 300
注意:这里有两个函数,其中domain()是原来的范围,range()是映射的范围。需要注意他们的写法。
序数比例尺
有时候,定义域和值域不一定是连续的。要让他们一一映射则需要序数比例尺。
建立一个映射关系
例如:
var index = [0, 1, 2, 3, 4];
var color = ["red", "blue", "green", "yellow", "black"];
和前面不一样,他们是两个不连续的数组,要求两个数组一一对应
代码如下:
//注意高版本的使用的是d3.scaleOrdinal(),低版本的使用的是d3.scale.ordinal()
var ordinal = d3.scaleOrdinal()
.domain(index)
.range(color);ordinal(0); //返回 red
ordinal(2); //返回 green
ordinal(4); //返回 black
有的使用我们需要将一些汉字映射到对应的数据可以使用如下
var object=[‘语文‘,‘数学‘,‘物理‘,‘生物‘,‘化学‘,‘英语‘]
我们可以将上面的函数映射成对应的数字
//注意高版本的使用的是d3.scaleBand(),低版本的使用的是d3.scale.ordinal().rangeBands()
var scaleY=d3.scaleBand()
.domain(object)
.rangeRound([0,g_height])
.
console.log(scaleY(‘语文‘)) //0
console.log(scaleY(‘数学‘)) //91
console.log(scaleY(‘英语‘)) //455
//还可以通过scaleY.bandwidth()获取每个映射点的间距
坐标系
v3版本
定义坐标轴的构造函数
var axis_x = d3.svg.axis().scale(比例尺)
.orient(‘top‘) // 刻度与坐标轴方向
.ticks(5) // 分成5等分,有时d3会根据可用空间和它自己的计算多画几个或者少画几个
.tickSubdivide(4) // 每个大刻度之间再画4个等分刻度
.tickPadding(10) // 刻度值与坐标轴之间的距离
.tickFormat(function(v) { // 格式化刻度值
return v + ‘天‘;
});
//使用坐标轴
svg.append(‘g‘)
.call(axis_x)
v4版本
//定义坐标轴的构造函数
var axisY=d3.axisLeft(scaleY).ticks(5) // 分成5等分,有时d3会根据可用空间和它自己的计算多画几个或者少画几个
.tickSubdivide(4) // 每个大刻度之间再画4个等分刻度
.tickPadding(10) // 刻度值与坐标轴之间的距离
.tickFormat(function(v) { // 格式化刻度值
return v + ‘天‘;
});
他的位置可以使用:axisLeft,axisBottom,axisTop,axisRight
//调用
g.append("g").call(axisY)
饼状角度生成器
//定义角度生成器的构造函数
var angle=d3.pie().value(function(d){ return d})
//定义颜色生成器构造函数
var color=d3.schemeCategory10
//生成饼状图
g.selectAll("path") .data(angle(data)) //使用角度 .enter() .append("path") .attr("d",arc).attr("fill",function(data,i){ return color[i] //使用颜色 })
d3中可以发送网络请求,可以自行百度,比较简单
标签:疑惑 ons divide move insert 的区别 nod 理解 pat
原文地址:https://blog.51cto.com/5493817/2524687