上周五我再团队里完成了前端qiankun微服务架构单镜像部署方案的分享,这件事终于告一段落了,这件事本身是一件很有价值的事情,能够较低很大的部署,运维成本。但由于研究期间本职的工作内容排的很满,而且中间又经历了曲折的绩效考核。所以一拖再拖。终于告一断落了。
于是我开始思考,下一阶段研究点什么那?
除了工作之外的学习内容,我给自己的要求是必须要学点区别于其他人的,着眼于未来的学习内容。在接触了node-red 与 butterfly 之后,我发现它们都使用了d3,大家一致都说d3是一个学习曲线很陡的js库,网上一直有他的传说。
很多优秀的软件只是用了太它的一点皮毛,就让软件增色很多,比如node-red的节点编排,butterfly的节点排版。所以我决定花点时间,好好学习一下它。
首先我先大致浏览了d3的文档,然后看了b站的使用d3进行数据可视化编程的视频。
感觉也不是很难吧,相对于echarts具有丰富的案例,d3只是提供很底层的api,想创造什么,看你的创造力了。
如果不知道的怎么学习一样东西时,可以先试着模仿。
用d3做一些常用的图表,照着echarts的案例做。
人类最开始的学习就是模仿。
就像我的女儿学习拍手,走路,吃饭。
学习d3先来个柱状图吧
照着b站的视频,我也敲出来了这样一个柱状图。
很简单的一个柱状图,但用到的知识却很多,坐标系,比例尺,svg操作,一个基础图例用到的都用到了。
下面我来总结一下开发的思路。
首先定义svg,与源数据
svg 的容器
<svg width="1600" height="800" id="main" class="svg"></svg>
使用的源数据
const data = [
{name: 'a', value: 1},
{name: 'b', value: 2},
{name: 'c', value: 3},
{name: 'd', value: 4},
{name: 'e', value: 5},
]
获取容器和设置容器的margin
const svg = d3.select('#main');
const width = svg.attr('width');
const height = svg.attr('height');
const margin = {top: 60, right:30, bottom: 60,left:50}
const innerWidth = width - margin.right - margin.left
const innerHeight = height - margin.top - margin.bottom
然后就是创建x轴的比例尺,和y轴的比例尺
const xScale = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([0, innerWidth])
const yScale = d3.scaleBand()
.domain(data.map(x => x.name))
.range([0, innerHeight])
.padding(0.5)
注意新的api的使用d3.scaleLinear()
,d3.scaleBand()
, domain()
, range()
, padding()
。我们一个一个学习一下。
d3.scaleLinear()
创建一个连续线性的比例尺,就是连续数字的映射。。简单地说,比例尺就相当于是一个函数,让我们把一组定义域映射到值域。
后面的domain()和range(),两个函数都是又来修饰 该比例尺的。常见的使用场景时这样的, svg 长 1200px,我们可以将
0到1200 映射成 0到原数据的最大值。这样,原数据中的任意一个值都可以使用该比例尺找到自己的位置。所以 domain()函数是用来设置定义域,range()是用来设置值域的。
domain的参数取自 数据集中, range的参数取自容器 svg的长宽。
scaleBand() 创建一个序列的条状比例比例尺,它的定义域是一个类目的集合,如,['苹果','橘子','梨','香蕉','火龙果','西瓜']
在这里 定义域就是 domain(data.map(x => x.name))
元数据名称的集合。
设置完比例尺 就要设置 坐标轴 和渲染数据了
const g = svg.append('g').attr('id', 'maingroup').attr('transform',`translate(${margin.left},${margin.top})`)
const yAxis = d3.axisLeft(yScale)
g.append('g').call(yAxis)
const xAxis = d3.axisBottom(xScale)
g.append('g').call(xAxis).attr('transform', `translate(0, ${innerHeight})`)
data.forEach(d => {
g.append('rect')
.attr('width', xScale(d.value))
.attr('height', yScale.bandwidth())
.attr('fill', 'green')
.attr('y', yScale(d.name))
})
代码解释,待续。。。