前言
D3JS的简单学习
安装
npm install d3
import * as d3 from "d3";
选择元素
select() : 通过匹配给定的CSS选择器,仅选择一个DOM元素.如果给定的CSS选择器有多个元素,则只选择第一个元素.
selectAll() : 通过匹配给定的CSS选择器来选择所有DOM元素
例如:
d3.select("div")
d3.select(".myclass").text()
d3.select("#hello").text()
常用方法
text: 读写文字内容
//读
d3.select('#pie').text()
//写,会替换原来的内容
d3.select('#pie').text('eee');
append: 将新元素作为当前选择中元素的最后一个子元素追加。 此方法还可以修改元素的样式,其属性,HTML和文本内容。
d3.select('#pie').append('span').text('aa');
这个试了一下,只能添加标签
html: 读取和设置html
d3.select('#pie').html()
试了一下,标签内部是文字就返回文字,是html就返回html。追加时会替换掉原来的内容
attr: 读写html的属性
d3.select('#pie').attr('title')
试了一下只能读写到当前对象,对应对象内部的html无法读取到。
style: 只能读写当前对象的样式
d3.select('#pie').style('color','red');
console.log(d3.select('#pie').style('color'));
一次只能读写一个样式
classed:用于设置HTML元素的"class"属性
//添加类
d3.select(".myclass").classed("myanotherclass", true);
//删除类
d3.select(".myclass").classed("myanotherclass", false);
//检查是否存在该类
d3.select(".myclass").classed("myanotherclass");
selectAll: 选择符合条件的所有元素
数据连接
什么是数据连接?
数据连接使我们能够注入,修改和删除元素(HTML元素)以及基于现有HTML文档中的数据集的嵌入式SVG元素.默认情况下,数据集中的每个数据项对应于文档中的元素(图形).
随着数据集的变化,也可以轻松操作相应的元素.数据连接在我们的数据和文档的图形元素之间创建了一种紧密的关系.数据连接使得基于数据集的元素操作变得非常简单和容易.
四种方法:
datum: 用于为HTML文档中的单个元素设置值。 一旦使用选择器选择元素,就会使用它。
<p></p>
d3.select('p')
.datum(50)
.text(function(d) {
return '在p标签里添加的值是:' + d;
});
从结果来看可以用来添加变量
data: 用于将数据集分配给HTML文档中的元素集合。 使用选择器选择HTML元素后使用它。
<ul id="list">
<li>5</li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
d3.select('#list').selectAll('li')
.data([10, 0, 30, 25, 15])
.text((d) => d);
第一点:只写data
是无效的,必须使用text
、html
这类的来写入数据
第二点:写入的数据会替换掉原来的数据
第三点:如果dom元素不存在,就不会生效
enter: 输出之前没有图形元素的数据项集。
这个挺难理解的,特地查了一下。以下面这个例子为例:
<ul id="list">
<li></li>
</ul>
d3.select('#list').selectAll('li')
.data([10, 20, 30, 25, 15])
.text(function(d) { return '之前存在的 ' + d; })
.enter()
.append('li')
.text(function(d) { return '后来创建的 ' + d; });
data里有5个数据,实际上只一个li
元素。这里enter起的作用就相对于占位,占位后通过append
往这个位置放入一个元素
exit: 输出不再存在数据的图形元素集。
<ul id="list">
<li></li>
<li></li>
<li>多余的</li>
<li>多余的</li>
</ul>
d3.select('#list').selectAll('li')
.data([10, 20])
.text(d => d)
.exit()
.remove();
实际上有4个元素,但是data里只有两个数据。exit
作用相对于来标识那些是多余的,再通过remove
可以将多与的删除
Data Function
在使用data后,原来的text等方法内部可以使用匿名函数,匿名函数里可以获取到对应的值和索引
<ul id="list">
<li></li>
<li></li>
</ul>
d3.select('#list').selectAll('li')
.data([10, 20])
.text((d,i) => {
console.log('值:',d,',索引:',i,',this:',this);
return d;
});
svg
svg的内容不介绍了,不熟悉的可以看一下:svg的简单学习 ,简单了解一些基础知识。这里主要记录使用d3来操作svg
示例:
// 获取容器并创建一个svg
d3.select('#svgContainer').append('svg').attr('width', 300).attr('height', 300)
// 绘制一条直线
.append('line').attr('x1', 100).attr('y1', 100).attr('x2', 200).attr('y2', 200).style('stroke', 'blue').style('stroke-width', 2);
Transition 过度
transition()方法适用于所有选择器,它启动过渡进程.此方法支持大多数选择方法,如-attr(),style()等.但是,它不支持append()和data()方法,这些方法需要在transition()方法之前调用.此外,它提供了特定于转换的方法,如duration(),ease()等.
// 过度时间
let t = d3.transition().duration(3000);
d3.select('#box')
.style('width','300px')
.style('height','100px')
.transition(t)
.style('background-color', 'lightblue');
注: 有关很重要的地方是:过度效果只会对transition(t)
后面的样式生效。比如上面的只会对背景色起过度效果。
动画
d3中没有animation
这个东西,动画的实现还是需要基于过度
duration: 过度时间
d3.selectAll("h3").transition().style("color","green").duration(5000);
delay: 延迟
d3.select('#box')
.style('width','300px')
.style('height','100px')
.transition()
.style('background-color', 'lightblue')
.delay(2000).duration(2000);
绘制图表
柱状图
// 数值
var data = [10, 5, 12, 15];
// 定义svg的宽
var width = 500;
// 定义 缩放到屏幕上可见的像素值。
var scaleFactor = 20;
// 柱状图的高
var barHeight = 30;
// 获取到一个svg
var graph = d3
.select('#box')
.append('svg')
.attr('width', width)
.attr('height', barHeight * data.length);
// g标签分组用的
var bar = graph
.selectAll('g')
.data(data)
.enter()
.append('g')
// 平移确定4个柱状图的位置
.attr('transform', function (d, i) {
return 'translate(0,' + i * barHeight + ')';
});
// 绘制矩形
bar.append('rect')
.attr('width', function (d) {
// 10*20 = 200 像素值
// 直接返回 '200px' 也可以
return d * scaleFactor;
})
.attr('height', barHeight - 1)
// 设置柱状图的填充颜色
.attr('fill','red');
// 添加文本
bar.append('text')
// 通过偏移量来设置文本的位置
.attr('x', function (d) {
return d * scaleFactor;
})
.attr('y', barHeight / 2)
.attr('dy', '.35em')
// 设置文字颜色
.attr('fill','blue')
.text(function (d) {
return d;
});
饼图
在开始绘制饼图之前,我们需要了解以下两种方法:
d3.arc()方法
d3.pie()方法
让我们详细了解这两种方法。
d3.arc()方法:d3.arc()方法生成一个弧。 您需要为弧设置内半径和外半径。 如果内半径为0,则结果将为饼图,否则结果将为圆环图
d3.pie()方法:d3.pie()方法用于生成饼图。 它从数据集中获取数据并计算饼图的每个楔形的起始角度和结束角度。
从网上找了个例子,从头捋顺了一下
<svg id="abc" />
// 创建一个svg
let svg = d3.select('#abc').append('svg').attr('width',350).attr('height',400);
// 数据源
let data = [{label: '电影',value: 50},{label: '电视剧',value: 60},{label: '动漫',value: 100}];
// 颜色
let colors = ['#5c84f2','#C8D0E6','#dddddd'];
// 创建一个饼图
let pie = d3.pie().value(d => d.value);
// 饼图数据
let pieData = pie(data);
// 创建饼图的弧路径
let arcPath = d3.arc().innerRadius(60).outerRadius(100);
// 创建分组,每一组里保存一个扇形信息
let arcList = svg.selectAll('g')
.data(pieData)
.enter()
.append('g')
.attr('transform','translate(150,200)');
// 在组里添加路径
arcList.append('path')
.attr('d',d => arcPath(d))
.attr('fill',(d,i) => colors[i])
.attr('stroke','black')
.on('mouseover',function(e,d) {
d3.select(this)
.attr('fill','#f8aba6');
})
// e是事件对象,d是数据对象
.on('mouseout',function(e,d) {
d3.select(this)
.attr('fill',colors[d.index]);
});
/* 上面的代码是绘制饼图,下面绘制饼图的文字 */
// 绘制扇形区域的数值
arcList.append('text')
.attr('fill','white')
.attr('text-anchor','middle')
.attr('transform',function(d) {
// 获取弧的中线点
var x = arcPath.centroid(d)[0];
var y = arcPath.centroid(d)[1];
return 'translate(' + x + ',' + y + ')';
})
.text(d => d.value);
// 绘制扇形区域对应的类型,就是线条加类型
arcList.append('line')
.attr('stroke',(d,i) => colors[i])
.attr('x1',function(d) { return arcPath.centroid(d)[0] * 1.34; })
.attr('y1',function(d) { return arcPath.centroid(d)[1] * 1.34; })
.attr('x2',function(d) { return arcPath.centroid(d)[0] * 1.8; })
.attr('y2',function(d) { return arcPath.centroid(d)[1] * 1.8; });
arcList.append('text')
.attr('fill',(d,i) => colors[i])
.attr('transform',function(d) {
var x = arcPath.centroid(d)[0] * 1.9;
var y = arcPath.centroid(d)[1] * 1.9;
return 'translate(' + x + ',' + y + ')';
})
.attr('text-anchor','middle')
.text(d => d.data.label);