已被阅读 1151 次 | 文章分类:javascript | 2022-05-04 01:09
D3.js是用于 HTML 和 SVG 实现的 JavaScript 可视化库。基于数据操作文档的 JavaScript 库。
什么是 D3.js?
D3.js是用于 HTML 和 SVG 实现的 JavaScript 可视化库。基于数据操作文档的 JavaScript 库。
说到D3不得不提到Echarts,Echarts和D3都是一个数据可视化的工具;而且都能实现一些相同的可视化图效果;那他们有什么不同呢?区别还是很大的
库层面的不同:
1 D3使用svg绘制图形,echarts使用canvas绘制图形
2 D3代码自由度高,相当灵活,但是学习成本也大;相反echarts封装性强,通过配置参数即可简单上手,但是不够灵活扩展性低;对于绝大多数项目够用了
应用场景:
1 如果只是展示一些静态图表;或者有少数鼠标点击、悬浮等效果的图表用echarts首选
2 如果说对绘制的DOM图表有频繁的鼠标交互操作,比如编辑、删除修改等那么echarts首选;D3中的每个图形都是一个标签,可以方便的进行增删操作
1 实现效果
D3能实现的效果还是很丰富的,大家感兴趣可以去官网demo查看https://observablehq.com/@d3/gallery
首先展示下本系列1和2能实现的简单demo效果
普通柱状图:
动起来的柱状图:
鼠标悬浮动画
交互的导图
力导向图
动态添加实体
2 基础语法
2.1 datum() 方法
将数据绑定到同一个元素上
代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>datum():绑定一个数据到选择集上</title>
<script src="../d3/d3.js"></script>
</head>
<body>
<p>1</p>
<p>2</p>
<p>3</p>
<p>4</p>
<script>
var body = d3.select("body"); //选择文档中的body元素
var p = body.selectAll("p");
var str=["dog","cat","snake"];
p.datum(str).text(function(d,i){
return "第"+i+"个p"+":"+" "+d;
})
</script>
</body>
</html>
2.1 data()
将数据跟元素按顺序对应绑定;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>data():绑定一个数组到选择集上</title>
<script src="../d3/d3.js"></script>
</head>
<body>
<p></p>
<p></p>
<p></p>
<p></p>
<script>
var body = d3.select("body"); //选择文档中的body元素
var p = body.selectAll("p");
var dataset = ["I like dogs","I like cats","I like snakes"];
p.data(dataset);
p.text(function(d,i){
return "第"+i+"个p"+":"+" "+d;
})
</script>
</body>
</html>
2.3 链式操作
这里涉及一个概念:选择集
使用 d3.select() 或 d3.selectAll() 选择元素后返回的对象,就是选择集。
另外,有人会发现,D3 能够连续不断地调用函数,形如:
d3.select().selectAll().text()
这称为链式语法,和 JQuery 的语法很像,常用 JQuery 的朋友一定会感到很亲切。
因为封装每个方法的时候都会返回当前对象 return this;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>选择集</title>
<script src="../d3/d3.js"></script>
</head>
<body>
<script>
var body = d3.select('body'); // 选择body元素
body.append('h1') // 向 body元素中插入 h1标签
.text('Hello xiaobai') // 给h1标签填充文字为hello world
.style('color','red'); // 修改样式 字体颜色 为红色
</script>
</body>
</html>
2.4 增加和删除元素
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>增删元素</title>
<script src="../d3/d3.js"></script>
</head>
<body>
<h1 id='app'>我h1</h1>
<script>
var h1 = d3.select('h1');
// 插入元素
var body = d3.select('body');
body.append('h2').text('我是插在body 末尾的元素');
body.insert('h2','#app').text('我是插在id为APP的元素前面的 h2标签')
//删除元素
var app = d3.select('#app');
app.remove(); //删除 id为app的元素
</script>
</body>
</html>
3 图表语法
3.1 基础柱状图
先简单解释svg和canvas
SVG 是什么
SVG,指可缩放矢量图形(Scalable Vector Graphics),是用于描述二维矢量图形的一种图形格式,是由万维网联盟制定的开放标准。
SVG 使用 XML 格式来定义图形,除了 IE8 之前的版本外,绝大部分浏览器都支持 SVG,
可将 SVG 文本直接嵌入 HTML 中显示。
SVG 有如下特点:
SVG 绘制的是矢量图,因此对图像进行放大不会失真。
基于 XML,可以为每个元素添加 JavaScript 事件处理器。
每个图形均视为对象,更改对象的属性,图形也会改变。
不适合游戏应用。
要注意,在 SVG 中,x 轴的正方向是水平向右,y 轴的正方向是垂直向下的。
Canvas 是什么
Canvas 是通过 JavaScript 来绘制 2D 图形,是 HTML 5 中新增的元素。
Canvas 有如下特点:
绘制的是位图,图像放大后会失真。
不支持事件处理器。
能够以 .png 或 .jpg 格式保存图像
适合游戏应用
代码和效果如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>柱状图</title>
<script src="../d3/d3.js"></script>
</head>
<body>
<script>
var w = 400,h = 400;
var body = d3.select('body'); //选择 body元素
var data = [50,100,200,150];
var svg = body.append('svg'); //在body中插入svg 元素 画布
svg.selectAll('rect') // 选择svg 中的rect(svg 中提供的矩形标签) 元素
.data(data) // 绑定数据
.enter() // 当 data.length > rect 的元素个时候用enter()。 update,exit()以后再说
.append('rect') // 补充data.length - rect.length 剩余的rect元素
.attr('x',20) // 上面说了SVG画布的坐标问题 x就是横向坐标的距离
.attr('y',function(d,i){ // Y也一样 都是相对 (0,0)点
return 25 * i;
})
.attr('width',function(d,i){ // 设置矩形的宽度
return d;
})
.attr('height',function(d,i){ //设置柱子的高度
return 20;
})
.attr('fill','green'); // 给柱子填充颜色
// 其实跟canvas 中的fillrect 绘制矩形一样
</script>
</body>
</html>
数据映射:上面数据是具体指定的数组,这里介绍一下用线性比例尺的方式绘制映射数据
线性比例尺,能将一个连续的区间,映射到另一区间。要解决柱形图宽度的问题,就需要线性比例尺。
比如将[0.3,0.9,1,2,2.5]这组数据用柱状图绘制,显然值太小;那么可有利用相关方法做映射,这里我们将上面的数据集映射到0-300的范围;
var dataset = [0.3,0.9,1,2,2.5]; //要把这个区间映射到0-300的范围
var max = d3.max(dataset);
var linear = d3.scaleLinear()
.domain([0,max])
.range([0,300]);
// 用比列尺转换为柱状图 就以上面那个线型比例尺为列
var body = d3.select('body'); //选择 body元素
var svg = body.append('svg'); //在body中插入svg 元素 画布
svg.selectAll('rect')
.data(dataset)
.enter()
.append('rect')
.attr('x',20)
.attr('y',function(d,i){
return i * 25;
})
.attr('width',function(d,i){
return linear(d);
})
.attr('height',function(d,i){
return 20;
})
.attr('fill','blue');
3.2 带坐标轴的柱状图
首先绘制上面3.1的映射柱状图;接下来是创建坐标轴的代码
// 创建比例尺
var linear = d3.scaleLinear().domain([0, max]).range([0, 300]);
添加坐标轴
//添加坐标轴
var axis = d3
.axisBottom() // v4: axisBottom 表示向下的比例尺 v3: d3.svg.axis().scale(linear).orient('bottom').ticks(5) v4 和v3差别真大
.scale(linear) // 指定比例尺
.ticks(5); // 指定刻度数量
svg.append('g') // svg 提供的标签,不知道的可以去熟悉下svg
.attr('transform', function (d, i) {
return 'translate(' + 20 + ',' + 25 * 5 + ')'; // 把坐标轴移到对应的位置
})
.call(axis);
3.3 坐标轴和标注
(1)添加svg画布
// 画布大小
var width = 400;
var height = 400;
// 在 body 里添加一个 SVG 画布
var svg = d3
.select('body')
.append('svg')
.attr('width', width)
.attr('height', height);
// 画布周边的空白
var padding = { left: 30, right: 30, top: 20, bottom: 20 };
(2)定义数据集
// 定义一个数组
var dataset = [10, 20, 30, 40, 33, 24, 12, 5];
(3)定义x和y轴
// x轴的比例尺
var xScale = d3.scale
.ordinal()
.domain(d3.range(dataset.length))
.rangeRoundBands([0, width - padding.left - padding.right]);
// y轴的比例尺
var yScale = d3.scale
.linear()
.domain([0, d3.max(dataset)])
.range([height - padding.top - padding.bottom, 0]);
// 定义x轴
var xAxis = d3.svg.axis().scale(xScale).orient('bottom');
// 定义y轴
var yAxis = d3.svg.axis().scale(yScale).orient('left');
(4)矩形柱状图
// 矩形之间的空白
var rectPadding = 4;
// 添加矩形元素
var rects = svg
.selectAll('.MyRect')
.data(dataset)
.enter()
.append('rect')
.attr('class', 'MyRect')
.attr(
'transform',
'translate(' + padding.left + ',' + padding.top + ')'
)
.attr('x', function (d, i) {
return xScale(i) + rectPadding / 2;
})
.attr('y', function (d) {
return yScale(d);
})
.attr('width', xScale.rangeBand() - rectPadding)
.attr('height', function (d) {
return height - padding.top - padding.bottom - yScale(d);
});
(5)添加文字标注
// 添加文字元素
var texts = svg
.selectAll('.MyText')
.data(dataset)
.enter()
.append('text')
.attr('class', 'MyText')
.attr(
'transform',
'translate(' + padding.left + ',' + padding.top + ')'
)
.attr('x', function (d, i) {
return xScale(i) + rectPadding / 2;
})
.attr('y', function (d) {
return yScale(d);
})
.attr('dx', function () {
return (xScale.rangeBand() - rectPadding) / 2;
})
.attr('dy', function (d) {
return 20;
})
.text(function (d) {
return d;
});
(6)添加x和y轴
// 添加x轴
svg
.append('g')
.attr('class', 'axis')
.attr(
'transform',
'translate(' + padding.left + ',' + (height - padding.bottom) + ')'
)
.call(xAxis);
// 添加y轴
svg
.append('g')
.attr('class', 'axis')
.attr(
'transform',
'translate(' + padding.left + ',' + padding.top + ')'
)
.call(yAxis);
QQ:3410192267 | 技术支持 微信:popstarqqsmall
Copyright ©2017 xiaobaigis.com . 版权所有 鲁ICP备17027716号