文章目录
SVG入门知识
- 今天开始学习d3.js,将笔记整理为博客以记录自己的学习过程。
- 视频资源来自于B站Up主 小魁少爷,是一位清华大学的学长,使用的好像是D3 version 5+,很适合初学者观看。
- 目前采用的学习策略是先过一遍视频(因为时常没多长),接着再过一遍官方的教学文档,并上手做一些可视化项目
- 所有参考资源我附在了文末
SVG简介
svg与 jpeg,png的区别
- 由于jpeg,png的像素表达能力有限,因此放大一百倍后会出现失真的现象。
- svg操作的是矢量图,无论如何扩大,都会按照相应的比例重新勾画图。因此无论分辨率是多少,使用d3.js绘制的图像不会失真
SVG与Canvas的区别
- Canvas是基于位图的,放大会影响到图片的显示效果,而SVG不会。
SVG常用于地图等需要经常放大/缩小的应用场景 - Canvas 绘制的图像都是Canvas的一部分,不能用js获取已经绘制好的图形元素,想**改变里面某个元素的位置或者变化需要重新绘制;**而SVG绘图时,每个图形都是以DOM节点的形式插入到页面中,可以用js或其他方法直接操作。
DOM
Document Object Model: 对父标签的操作会影响到子标签
函数式编程
let f = function(a,b){return a+b}
等价于: const myFunction = (a,b) => a+b
把字符串转换成数值
+(‘3.14’)
对SVG的操作
标签的选择(select() 选择Id, selectAll()选择 class 和 tag)
层级查询(通过父标签筛选子标签)
坐标系
在d3中,使用的坐标系不是平面直角坐标系,而是Canvas坐标系
- 普通图形:x,y
- 原型: cx,cy
属性的查询与赋值
select().attr('key') // 查询
select().attr('key','value') // 赋值
比例尺(Essential)
- 比例尺用于把实际的数据空间映射到屏幕的空间
- 比例尺非常重要,会经常同时传给坐标轴与数据
某一个像素,它到底对应的是真实数据的多少
比例尺的应用
const myscale = d3.scaleLinear().domain([data_min,data_max]).range([map_min,map,max]) // 线性比例尺
myscale(value)
const myscale2 = d3.scaleBand().domain().range
注意:
- domain和range中的参数值是一个数组,不是两个值
- domain中的数组存放的是数据集中的最大值和最小值
- range中的数组存放的是我们希望映射出的最大值和最小值
本节课示例代码 (demo1-基本图形.html)
<!DOCTYPE html>
<html>
<head>
<title>firstDemo</title>
<script src="./js/d3.min.js"></script>
</head>
<body>
<svg width="1500" height="800" id="mainsvg" class="svgs"></svg>
<script>
const data = [
{name:"AAA",value:56},
{name:"BBB",value:20},
{name:"CCC",value:43},
{name:"DDD",value:15},
{name:"EEE",value:67},
{name:"FFF",value:45},
{name:"GGG",value:31},
{name:"HHH",value:24},
{name:"I I I",value:78}
]
const svg = d3.select('#mainsvg');
const width = +svg.attr('width');
const height = +svg.attr('height');
const margin = {top:180 ,left:100, right:60, bottom:100};
const innerWidth = width - margin.left - margin.right; //作图区域
const innerHeight = height - margin.top - margin.bottom; // 作图区域
const xScale = d3.scaleLinear()
.domain([0,d3.max(data,d => d.value)])
.range([0,innerWidth]);
const yScale = d3.scaleBand()
.domain(data.map( d => d.name ))
.range([0,innerHeight])
.padding(0.1);
//padding:间隔
const yAxis = d3.axisLeft(yScale);
const xAxis = d3.axisBottom(xScale);
const g = svg.append('g')
.attr('id', 'maingroup')
.attr('transform', `translate(${margin.left} , ${margin.top})`);//``这个反引号是ES6中新增的模板字符串,不是单引号!
/*
//最简单的坐标轴设置方式:
g.append('g').call(yAxis);
g.append('g').call(xAxis).attr('transform', `translate(0,${innerHeight})`);
*/
// 一般的坐标轴设置
const yAxisGroup = g.append('g').call(yAxis)
.attr('id', 'yaxis')
.append('text')
.text('Name')
.attr('font-size', '3em')
.attr('transform', 'rotate(-90)') // y-axis label needs an additional transform;
.attr('x', -innerHeight / 2)
.attr('y', -50)
.attr('fill', 'blue')
const xAxisGroup = g.append('g').call(xAxis)
.attr('id', 'xaxis')
.attr('transform', `translate(${0}, ${innerHeight})`)
.append('text')
.text('Value')
.attr('font-size', '3em')
.attr('x', innerWidth / 2)
.attr('y', 50)
.attr('fill', 'blue');
data.forEach(d => {
g.append('rect')
.attr('width',xScale(d.value))
.attr('height',yScale.bandwidth())
.attr('fill','green')
.attr('y', yScale(d.name))
.attr('opacity',0.8 );
});
/**
width: 矩形的宽
height: 矩形的高
fill :填充颜色
y :矩形位置,如果不设置默认为0;这相当于maingroup中的y值
x值不需要设置,默认为0
*/
//设置坐标轴文字大小
d3.selectAll('.tick text').attr('font-size', '2em');
//添加标题
g.append('text').text('This is my first D3.js demo').attr('font-size','3em')
.attr('transform', `translate(${innerWidth/2},-10)`)
.attr('text-anchor', 'middle');
</script>
</body>
</html>