D3可视化:(1)初次见面,SVG与D3的魅力

栏目: 后端 · 前端 · 发布时间: 5年前

内容简介:D3.js是一个基于HTML/SVG/CSS的数据可视化库,是领域内非常强大的存在了。今后会在工作使用,也因此开始了自学之旅。学习过程中,我主要通过Curran Kelleher老师的系列教程进行学习,这个笔记用于学习、整理和分享,陆续学习、更新和记录中....完成效果图:

D3.js是一个基于HTML/SVG/CSS的数据可视化库,是领域内非常强大的存在了。

今后会在工作使用,也因此开始了自学之旅。学习过程中,我主要通过Curran Kelleher老师的系列教程进行学习,这个笔记用于学习、整理和分享,陆续学习、更新和记录中....

原文链接

学习目的:

  • 熟悉和认识D3.js
  • 练习使用SVG画图,熟悉操作
  • 练习D3.js的基本函数和操作

完成效果图: 在线demo

D3可视化:(1)初次见面,SVG与D3的魅力

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.selectd3.selectAll 返回的都是选择集,添加、删除以及修改都需要用到选择集,查看状态有三个函数可以使用:

selection.empty()
selection.node()
selection.size()

设定和获取属性

使用 selectselectAll 选择后,可以通过 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 构建轮廓

D3可视化:(1)初次见面,SVG与D3的魅力
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)可以发现,对三个圆圆心的操作 cxcy 出现了多次,而作用也仅仅是为了将圆放在中心。因此,可以通过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)
复制代码

第二步 嘴巴

D3可视化:(1)初次见面,SVG与D3的魅力

嘴巴实际上是一个弧线,使用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 的元素上,需要分别操作。

完整代码

code downlaod here

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的魅力》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Pragmatic Programmer

The Pragmatic Programmer

Andrew Hunt、David Thomas / Addison-Wesley Professional / 1999-10-30 / USD 49.99

本书直击编程陈地,穿过了软件开发中日益增长的规范和技术藩篱,对核心过程进行了审视――即根据需求,创建用户乐于接受的、可工作和易维护的代码。本书包含的内容从个人责任到职业发展,直至保持代码灵活和易于改编重用的架构技术。从本书中将学到防止软件变质、消除复制知识的陷阱、编写灵活、动态和易适应的代码、避免出现相同的设计、用契约、断言和异常对代码进行防护等内容。一起来看看 《The Pragmatic Programmer》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具