简介
D3(Data Driven Documents),数据驱动文档。
在Vue中使用
安装
npm install d3 --save
引用
在组件中引用
import * as d3 from 'd3'
使用D3操作SVG
SVG
SVG(Scalable Vector Graphics),可缩放矢量图形,使用XML格式定义图像。即两点之间的连线是直线的话,不论怎样放大直线,两点之间的连线永远是直线,即放大不会失真,具有画图细腻性的特点。
在html中使用svg
<svg></svg>
SVG常见属性
- id,class 特殊的属性,可以使用.attr设置
- x , y , cx , cy 屏幕坐标系,cx,cy表示圆心的坐标
- fill , stroke
- height , width, r 圆的半径
- transform -> translate, rotate, scale 平移/旋转/缩放
SVG属性非常多,且属性的取值范围和类型各不同,养成及时查阅的习惯非常重要
设置属性
设置/获取元素属性
element.attr('attr_name','attr_value') //设置属性
var value = element.attr('attr_name') //获取属性
使用D3添加或删除SVG元素
链式添加
const myRect = d3.select('#mainsvg').append('g').attr('id','maingroup').attr('height','100px') //设置id后继续设置高度
屏幕空间坐标系
屏幕空间的坐标系与常见的坐标系不用,屏幕坐标系具有以下特点(图二):
- 左上方为远点
- X、Y分别为水平向右、垂直向下
比例尺
- 比例尺用于把实际的数据空间映射到屏幕空间(一个像素对应多少数据)
- 比例尺非常重要,会经常同时传给坐标轴与数据
const mySale = d3.scaleLinear() //定义比例尺,返回值本质上是函数
const mySale = d3.scaleLinear().domain([0,10]).range([-1000,1000]) //配置比例尺,domain表示实际数据,range表示屏幕空间,上述语句表示将0-10的数据映射到屏幕-1000-1000的范围
mySale(5); //结果为0,5为0-10的中点,输出为-1000-1000的中点
使用D3生成柱状图
定义Margin
- SVG对于D3.js来说是一个画布
- SVG范围外的任何内容属于画布之外,浏览器不予显示
- D3只对上图Margin的区域进行操作,防止D3坐标轴画到屏幕外边
const margin = {top:60,right:30,bottom:60,left:50}; //定义margin ,数据可自定义
vue
<template>
<svg width="1400" height="800" id="id" class="svgs"></svg>
</template>
<script>
import * as d3 from 'd3'
export default{
data(){
return{
dataList:[
{name:'zby',value:12},
{name:'as',value:2},
{name:'asd',value:20},
{name:'gtr',value:17},
{name:'fgb',value:12},
{name:'ehr',value:19},
{name:'dsj',value:9},
]
}
},
mounted() {
this.showSvg();
},
methods:{
showSvg(){
const svg = d3.select('#id'); //使用id获取svg画布
const width = +svg.attr('width'); //+将字符串转为数字
const height = +svg.attr('height');
const margin = {top:100,right:30,bottom:60,left:150};
const innerWidth = width-margin.left-margin.right;
const innerHeight = height - margin.top - margin.bottom;
//定义比例尺
//x轴比例尺
const xScale = d3.scaleLinear()
//d3.max第一个参数指明操作对象,第二个参数值的意思是this.dataList['value'],然后取value最大值
.domain([0,d3.max(this.dataList, d=>d.value)]) //取决于渲染的值,此处取决于dataList
.range([0,innerWidth]);
//y轴比例尺
const yScale = d3.scaleBand()
.domain(this.dataList.map(d=>d.name)) //映射this.dataList['name']
.range([0,innerHeight])
.padding(0.1); //在y轴的每个变量中间预留位置
//定义中间位置
const g = svg.append('g').attr('id','maingroup')
.attr('transform', `translate(${margin.left},${margin.top})`);//将坐标轴移到margin左上角
//生成坐标轴
//定义y轴
const yAxis = d3.axisLeft(yScale);
g.append('g').call(yAxis); //把坐标轴容器填满,.call才是真正把坐标轴渲染出来的方法
//定义x轴
const xAxis = d3.axisBottom(xScale);
// g.append('g').call(xAxis);//x轴在上方
g.append('g').call(xAxis).attr('transform',`translate(0,${innerHeight})`); //将x轴平移到下方
//画柱状图
this.dataList.forEach(d=>{
g.append('rect')
.attr('width',xScale(d.value)) //以value的值渲染柱形图width
.attr('height',yScale.bandwidth()) //y轴默认宽度
.attr('fill','green') //柱形图颜色
.attr('y',yScale(d.name)) //柱形在y轴的渲染位置
})
}
}
}
</script>
<style>
</style>
Data-Join
Data-Join 本质上是将数据与图元进行绑定
- 每个国家的人数绑定到矩形的长度
- 疫情感染的人数绑定到圆的半径
使用Data-Join可以省去大量根据数据设置图元属性的代码量,对于动态变化的数据提供统一的接口
- 以数据为中心的可视化操作(根据数据的每个属性自动调整绑定图元的属性)
- 不再需要手动添加、修改、删除图元(会根据Data-Join的绑定自动推断)
- 如果图元的数目不等于数据的条目(根据数据条目的数量选定相应数量的图元)
D3.js绑定数据的三个状态
- Update 图元与数据条目相同,上述均为单纯的update
- Enter 数据的条目多于图元甚至没有图元,常用于第一次绑定数据
- Exit 数据的条目少于图元甚至没有数据,常用于结束可视化
使用Enter实现柱状图
画柱状图部分的代码改为列下的代码
//enter前的语句用于占位,enter后d3由enter进入update状态,当dataList不为空时将自动渲染,data用于绑定渲染的数据对象
g.selectAll('.dataRect').data(this.dataList).enter().append('rect')
.attr('class','dataRect')
.attr('width',d=>xScale(d.value))
.attr('height',yScale.bandwidth())
.attr('y',d=>yScale(d.name))
.attr('fill','green')
.attr('opacity',0.8)
CSV数据
常见的CSV文件数据格式为
- 第一行是属性列表
- 后续每行对应一条数据
- CSV本质上是纯文本,区别于EXCEL格式
D3读取CSV数据
d3.csv('path/to/data.csv').then(data =>{})
- .csv函数 的返回值是一个JS的Promise对象(Promise对象用于执行异步操作)
- .then() 的参数为一个函数 ,参数为.csv的返回值
- d3.csv() 会正常向服务器请求数据,在请求并处理好之后,将结果扔给.then()中的回调函数。
d3.csv('path/to/data.csv').then(data=>{
data = data.filter(d=>d['地区'] !== '总计'); //保留地区不是总计的数据
data.forEach(d=>{
name = d['name'] //获取name属性
})
})
Path
path 元素是SVG基本形状中最强大的一个。可以用path绘制基本图形,包括贝塞尔曲线、2次曲线等
- path元素的形状是通过属性d来定义的,属性d的值是一个“命令+参数”的序列
path属性
d
fill 填充颜色
stroke 描边颜色
stroke-width 描边宽度