D3.js实现绘制折线图的教程详解
作者:FinGet 发布时间:2024-04-10 10:53:54
本章我们来实现一下折线图,有了画柱状图的经验,我们可以快速的分析出柱状图和折线图的区别主要是x轴比例尺和绘制数据图形,其余的画布,坐标轴等,本章就不过多的讲解了。
点击查看demo
x轴比例尺
根据折线图x轴的特点,可以分析出我们需要在x轴画出间隔相同的N的点,所以我们采用scalePoint
。
const xScale = d3.scalePoint()
.domain(data.map((d) => d.name))
.range([0, dimensions.boundedWidth]);
如果使用scaleBand
就会是下图的效果,刻度和数据点不能对齐。
数据折线
D3提供了一些图形构造器,例如d3.line
,d3.area
,d3.arc
,d3.pie
等,本章借着折线图,我们介绍一下d3.line
和d3.area
。
d3.line
通过点位的二维数组自动生成path:
// 构建一个默认为直线的线条绘制器
const lineGenerator = d3.line();
// 定义一下点位
const points = [
[0, 50],
[100, 200],
[300, 100],
[400, 150],
[300, 200]
];
// 生成一条path路径
const linePath = lineGenerator(points);
// 渲染line
svg.append("path")
.attr("d", linePath)
.attr("fill", "none")
.attr("stroke-width", 1)
.attr("stroke", "red");
指定x,y的取值方式
const points = [
{ x: 0, y: 50 },
{ x: 100, y: 200 },
{ x: 300, y: 100 },
{ x: 400, y: 150 },
{ x: 300, y: 200 }
];
const lineGenerator = d3
.line()
.x((d) => d.x)
.y((d) => d.y);
const linePath = lineGenerator(points);
在实际开发中,我们基本上都是需要通过x轴和y轴的比例尺去计算,每个数据对应点的位置信息。
圆滑的曲线
const lineGenerator = d3
.line()
.x((d) => d.x)
.y((d) => d.y)
.curve(d3.curveBasis) // 曲线插值
D3提供了很多插值,例如:curveBasis
,curveCardinal
,curveCatmullRom
,curveStep
,curveStepBefore
,curveStepAfter
都可以试试效果
初步了解了d3.line
,我们就可以轻松的绘制我们的折线图了:
const line = d3.line()
.x((d) => xScale(xValue(d)))
.y((d) => yScale(yValue(d)));
chartG.append("g")
.append("path")
.style("fill", "none")
.style("stroke", "rgb(51, 209, 243)")
.style("stroke-width", 1)
.datum(data)
.attr("d", line);
复制代码
这里我们使用的是datum
,因为只需要一条折线,而且需要在这条折线上生成所有的数据的点位以构成path路径,如果忘了datum
和data
的区别,可以回顾一下DataJoin。
d3.area
除了可以绘制一条折线,我们还可以绘制一个填充的折线区域,这也是比较常见的使用场景,这就需要用到d3.area
。
d3.area
用来设置坐标的属性有六个x
,y
,x0
,y0
,x1
,y1
,它们通常分为两组来使用即:x, y0, y1
,y, x0, x1
分别代表两个方向水平和垂直。
水平方向
const areaGenerator = d3.area()
.x((d) => d.x)
.y1((d) => d.y)
.y0(10);
const areaPath = areaGenerator(points);
svg
.append("path")
.attr("d", areaPath)
.attr("fill", "none")
.attr("stroke-width", 1)
.attr("stroke", "red");
我们打印一下areaPath
:
M0,50L100,200L300,100L400,150L400,10L300,10L100,10L0,10Z
翻译一下:
移动到(0,50)->绘制线到(100,200)->绘制线到(300,100)->绘制线到(400,150)
->绘制线到(400,10)->绘制线到(300,10)->绘制线到(100,10)
->绘制线到(0,10)->闭合(将起点与终点连接)
其实理解起来就像是小学的拼音连线题一样:
垂直方向
const points = [ // y 是递增的
{ x: 20, y: 50 },
{ x: 100, y: 100 },
{ x: 300, y: 150 },
{ x: 200, y: 200 },
{ x: 300, y: 230 }
];
const areaGenerator = d3.area()
.y((d) => d.y)
.x0(10)
.x1((d) => d.x);
值得注意的是,水平方向的area,points的特点是按x
递增的,垂直方向的area,points的特点是按y
递增的。
不排序的话,你可能会得到一个意料之外的图形:
最后就可以完成我们的折线图area模式了:
const area = d3.area()
.x((d) => xScale(xValue(d)))
.y1((d) => yScale(yValue(d)))
.y0(yScale(0));
chartG.append("g")
.append("path")
.style("fill", "none")
.style("fill", "green")
.style("stroke", "rgb(51, 209, 243)")
.style("stroke-width", 1)
.datum(data)
.attr("d", area);
来源:https://juejin.cn/post/7162720725801893901


猜你喜欢
- Dreamweaver MX 2004的强大功能以及更加完善的人性化设置已经深受大家喜爱。在此笔者就谈
- 1.问题描述当我们在实用ElementUI组件完成项目的时候可能会遇到这样的需求,比如:新建一个活动,需要定义活动的时间范围;因此我们在新建
- 动态渲染就是有一个异步的数据,大概长这样:{ "inline": true, "labelPosition&q
- 🚩 前言本次实现了一个在浏览器中运行的简陋的人脸检测功能,由于水平有限,这里使用表单上传图片,只能一次检测一张人脸。实现过程中遇到的主要问题
- 目录背景什么是协程?什么是 gevent?协程的例子Q&AQ:gevent 无法捕获的耗时A:猴子补丁实践异步 requests 请
- 前言本文参照了大佬Andrew Ng的所讲解的Tensorflow 2视频所写,本文将其中只适用于Linux的功能以及只适用于Google
- 之前版本的代理中,可以使用fiddler进行HTTP包的代理,但是代理HTTPS包时,执行错误 self._sslobj.do_
- 概要基于 golang Gin 框架开发 web 服务时, 需要时不时的 go build , 然后重启服务查看运行结果.go build
- 在日常学习工作过程中,我们难免需要复用以前的项目,这里讲下复用 Django 项目并重命名的过程。1.修改项目名称,使用 pycharm -
- 目录socket概念socket基本用法创建tcp套接字创建udp套接字socket内建方法实现端口扫描总结socket概念socket又称
- Pytorch 使用GPU训练使用 GPU 训练只需要在原来的代码中修改几处就可以了。我们有两种方式实现代码在 GPU 上进行训练方法一 .
- 导包import “github.com/smartystreets/goconvey”核心API顶
- 所用拓展模块 xlrd: Python语言中,读取Excel的扩展工
- 目前,计算机上主流的操作系统有Windows、Unix、Mac OS等,os模块为多操作系统的访问提供了相关功能的支持,涉及对文件相关操作功
- 如果用户查询时,使用Order BY排序语句指定按员工编号来排序,那么排序后产生的所有记录就是临时数据。对于这些临时数据,Oracle数据库
- .data文件格式.data文件是用来存储数据的一种文件格式。之前通常数据是用逗号隔开或tab健隔开的格式,现在也可能是文本文件格式或二进制
- 先想创意,再画草图,接着鼠绘,最后做成flas * 。这是我的习惯流程。 这是想到中秋时,我第一时间内能浮想出的图像:大意是嫦娥奔
- 在项目中遇到后台数据还没有加载完毕,但是页面上调用了后台数据中的字段,这样就会报undefined。例如:一进入页面直接回显数据。我在cre
- 首先定义了一个test.py的文件,然后再定义一个函数,并在函数定义后直接运行:test.pydef HaveFun(): if __nam
- AjaxUpload.js文件的代码,供大家参考,具体内容如下/** * AJAX Upload ( http://valums.com/