内容简介:D3.js是一个基于HTML/SVG/CSS的数据可视化库,是领域内非常强大的存在了。今后会在工作使用,也因此开始了自学之旅。学习过程中,我主要通过Curran Kelleher老师的系列教程进行学习,这个笔记用于学习、整理和分享,陆续学习、更新和记录中....完成效果图:
D3.js是一个基于HTML/SVG/CSS的数据可视化库,是领域内非常强大的存在了。
今后会在工作使用,也因此开始了自学之旅。学习过程中,我主要通过Curran Kelleher老师的系列教程进行学习,这个笔记用于学习、整理和分享,陆续学习、更新和记录中....
原文链接
学习目的:
- 熟悉和认识D3.js
- 练习使用SVG画图,熟悉操作
- 练习D3.js的基本函数和操作
完成效果图: 在线demo
D3初印象
选择集
D3是实现数据可视化,仍然离不开传统DOM的选择和操作,也因此,D3提供了类似Jquery的DOM操作指令:
d3.select d3.selectAll
const svg = d3.select('svg') //选择svg const p = svg.selectAll('p') //选择svg下所有的p标签 复制代码
当然,可以使用 #id
以及 .class
对id和类进行选择
查看状态
d3.select
和 d3.selectAll
返回的都是选择集,添加、删除以及修改都需要用到选择集,查看状态有三个函数可以使用:
selection.empty() selection.node() selection.size()
设定和获取属性
使用 select
或 selectAll
选择后,可以通过 attr
获取和设定属性,可以使用 append
方法添加元素
const svg = select('svg'); svg.append('circle') .attr('r','30') 复制代码
使用D3和SVG画图
html文件
<html lang="en"> <head> <title>Smile face with d3</title> </head> <body> <svg width="960" height="500"></svg> <script src="https://d3js.org/d3.v5.min.js"></script> <script src="index.js"></script> </body> </html> 复制代码
主要内容通过index.js实现:
第一步:通过d3选择SVG,使用 circle
构建轮廓
const svg = d3.select('svg'); const height = +svg.attr('height'); const width = +svg.attr('width'); svg.append('circle') .attr('r',height / 2) .attr('cx', width / 2) .attr('cy', height / 2) .attr('fill', 'yellow') .attr('stroke','black') const leftEye = svg.append('circle') .attr('r', 30) .attr('cx', width / 2 - 100) .attr('cy', height / 2 - 80) .attr('fill', 'black') const rightEye = svg.append('circle') .attr('r', 30) .attr('cx', width / 2 + 100) .attr('cy', height / 2 - 80) .attr('fill', 'black') 复制代码
要点:
- 通过
attr
获取的属性是string
类型的,通过parseFloat
或者+
转换为number
类型 - 对圆形
circle
的属性cx
cy
等,使用变量作为其大小设置的值,而不用一个数字,方便日后的维护 - leftEye和RightEye用类似的方法,创造出来,并将眼睛放置在合适的位置。
代码优化
1)可以发现,对三个圆圆心的操作 cx
和 cy
出现了多次,而作用也仅仅是为了将圆放在中心。因此,可以通过SVG中的 <g>
来分组来实现一次性操作。
const g = svg.append('g') .attr('transform',`translate(${ width / 2}, ${ height / 2})`) //这样,在画圆的时候,就可以去掉对其圆心的操作,因为默认的位置就在中心了 const circle = g.append('circle') .attr('r',height / 2) .attr('fill', 'yellow') .attr('stroke','black') 复制代码
2)同样的,对于眼睛的操作,也有点繁琐,可以通过变量和分组,提高代码的可维护性能。
const eyeSpacing = 100; const eyeYoffset = -80 const eyeRadius = 30; const eyesG = g.append('g') .attr('transform', `translate(0, ${eyeYoffset})`); const leftEye = eyesG.append('circle') .attr('r', eyeRadius) .attr('cx', - eyeSpacing) const rightEye = eyesG.append('circle') .attr('r', eyeRadius) .attr('cx', + eyeSpacing) 复制代码
第二步 嘴巴
嘴巴实际上是一个弧线,使用SVG中的 path
进行绘制。熟悉 path
的,当然可以直接给参数进行绘制,但是d3对圆弧有更好的支持,可以使用 d3.arc
函数,方便的绘制圆弧。
arc函数
根据官方的API手册,函数的使用方法如下:
var arc = d3.arc(); arc({ innerRadius: 0, outerRadius: 100, startAngle: 0, endAngle: Math.PI / 2 }); // "M0,-100A100,100,0,0,1,100,0L0,0Z" 复制代码
其中,innerRadius是内圆半径,outerRadius是外圆半径,startAngle和endAngle分别是开始和结束的弧度(完整的圆是0~2PI)
笑脸的实现
根据以上内容,代码如下:
const mouth = g.append('path') .attr('d',d3.arc()({ innerRadius: 150, outerRadius: 170, startAngle: Math.PI /2, endAngle: Math.PI * 3 / 2 })) 复制代码
眉毛
眉毛用简单的长方形来代替,也就是svg中的 <rect>
,使用前文的编程风格,将眉毛归为一个group,并将位置设定。
const eyebrowWidth = 50; const eyebrowHeight = 10; const eyebrowYoffset = -150; const BrowG = g.append('g') .attr('transform',`translate(${-eyebrowWidth / 2},${eyebrowYoffset})`); const leftEyebrow = BrowG.append('rect') .attr('width',eyebrowWidth) .attr('height',eyebrowHeight) .attr('x',-eyeSpacing) const rightEyebrow = BrowG.append('rect') .attr('width', eyebrowWidth) .attr('height', eyebrowHeight) .attr('x', eyeSpacing) 复制代码
加入动画
使用 transition
函数设置眉毛的动画,让笑脸动起来
const BrowG = g.append('g') .attr('transform',`translate(${-eyebrowWidth / 2},${eyebrowYoffset})`); BrowG.transition().duration(2000) .attr('transform', `translate(${-eyebrowWidth / 2},${eyebrowYoffset - 50})`) .transition().duration(2000) .attr('transform', `translate(${-eyebrowWidth / 2},${eyebrowYoffset})`).duration(2000) 复制代码
注意点:
-
transition
函数要对号入座,即如果加在了<g>
上,对应的增加的属性动画应该在transform
上; 如果动画在<rect>
上,动画应该在y
属性上。 - 添加动画不能在
append
函数之后连接,比如BrowG.append('g').attr(...).transition()
是不行的。因为过度动画无法绑定在append
的元素上,需要分别操作。
完整代码
const svg = d3.select('svg'); const height = +svg.attr('height'); const width = +svg.attr('width'); const g = svg.append('g') .attr('transform',`translate(${ width / 2}, ${ height / 2})`) const circle = g.append('circle') .attr('r',height / 2) .attr('fill', 'yellow') .attr('stroke','black') const eyeSpacing = 100; const eyeYoffset = -80 const eyeRadius = 30; const eyebrowWidth = 50; const eyebrowHeight = 10; const eyebrowYoffset = -150; const eyesG = g.append('g') .attr('transform', `translate(0, ${eyeYoffset})`); const leftEye = eyesG.append('circle') .attr('r', eyeRadius) .attr('cx', - eyeSpacing) const rightEye = eyesG.append('circle') .attr('r', eyeRadius) .attr('cx', + eyeSpacing) const mouth = g.append('path') .attr('d',d3.arc()({ innerRadius: 150, outerRadius: 170, startAngle: Math.PI /2, endAngle: Math.PI * 3 / 2 })) const BrowG = g.append('g') .attr('transform',`translate(${-eyebrowWidth / 2},${eyebrowYoffset})`); BrowG.transition().duration(2000) .attr('transform', `translate(${-eyebrowWidth / 2},${eyebrowYoffset - 50})`) .transition().duration(2000) .attr('transform', `translate(${-eyebrowWidth / 2},${eyebrowYoffset})`).duration(2000) const leftEyebrow = BrowG.append('rect') .attr('width',eyebrowWidth) .attr('height',eyebrowHeight) .attr('x',-eyeSpacing) const rightEyebrow = BrowG.append('rect') .attr('width', eyebrowWidth) .attr('height', eyebrowHeight) .attr('x', eyeSpacing) 复制代码
以上所述就是小编给大家介绍的《D3可视化:(1)初次见面,SVG与D3的魅力》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。