D3 二维图表的绘制系列(六)基础折线图

D3 二维图表的绘制系列(一)介绍 1 介绍 D3 (或者叫 D3.js )是一个基于 web 标准的 JavaScript 可视化库. D3 可以借助 SVG, Canvas 以及HTML 将你的数据生动的展现出来. D3 结合了强大的可视化交互技术以及数据驱动 DOM 的技术,让你可以借助于现代浏览器的强大功能自由的对数据进行可视化 学习了d3一个多月,通过绘制一些简单的二维图表,总算入门了d3。强烈推荐《D3数据可视化实战... 阅读详情

上一篇: 横向柱状图 https://blog.youkuaiyun.com/zjw_python/article/details/98209333

下一篇: 堆叠面积图 https://blog.youkuaiyun.com/zjw_python/article/details/98214359

代码结构和初始化画布的Chart对象介绍,请先看 https://blog.youkuaiyun.com/zjw_python/article/details/98182540

本图完整的源码地址: https://github.com/zjw666/D3_demo/tree/master/src/lineChart/basicLineChart

1 图表效果

在这里插入图片描述

2 数据

date,money
Mon,120
Tue,200
Wed,150
Thu,80
Fri,70
Sat,110
Sun,130

3 关键代码

导入数据

d3.csv('./data.csv', function(d){
    return {
        date: d.date,
        money: +d.money
    };
}).then(function(data){
....

一些样式配置参数,折线图不同于柱状图,其网格线可能包括平行于X轴和Y轴两个方向

const config = {
        lineColor: chart._colors(0),
        margins: {top: 80, left: 80, bottom: 50, right: 80},
        textColor: 'black',
        gridColor: 'gray',
        ShowGridX: [],
        ShowGridY: [20, 40, 60, 80, 100, 120, 140, 160 ,180, 200, 220],
        title: '折线图',
        pointSize: 5,
        pointColor: 'white',
        hoverColor: 'red',
        animateDuration: 1000
    }

尺度转换,与柱状图类似

/* ----------------------------尺度转换------------------------  */
    chart.scaleX = d3.scaleBand()
                    .domain(data.map((d) => d.date))
                    .range([0, chart.getBodyWidth()])
    
    chart.scaleY = d3.scaleLinear()
                    .domain([0, (Math.floor(d3.max(data, (d) => d.money)/10) + 1)*10])
                    .range([chart.getBodyHeight(), 0])
    

渲染线条,这里运用了d3.line函数方便地绘制了包含一系列点地折线。值得注意的是,我们想要折线的由左向右逐渐显现的动画效果不能简单依靠属性动画了,这里先对数据点进行了线性插值,然后使用了中间帧attrTween动画达到效果。

/* ----------------------------渲染线条------------------------  */
    chart.renderLines = function(){

        let lines = chart.body().selectAll('.line')
                    .data([data]);

            lines.enter()
                    .append('path')
                    .classed('line', true)
                .merge(lines)
                    .attr('fill', 'none')
                    .attr('stroke', config.lineColor)
                    .attr('transform', 'translate(' + chart.scaleX.bandwidth()/2 +',0)')
                    .transition().duration(config.animateDuration)
                    .attrTween('d', lineTween);
            
            lines.exit()
                    .remove();
            
            //中间帧函数
            function lineTween(){
                const generateLine = d3.line()
                                        .x((d) => d[0])
                                        .y((d) => d[1]);

                const pointX = data.map((d) => chart.scaleX(d.date));
                const pointY = data.map((d) => chart.scaleY(d.money));

                const interpolate = getInterpolate(pointX, pointY);                
                
                const ponits = [];

                const interval = 1/(pointX.length-1);

                let index = 0;

                return function(t){
                    if (t - interval > 0 && t % interval < Math.pow(10, -1.4)){  //保证线条一定经过数据点
                        index = Math.floor(t / interval);
                        ponits.push([pointX[index], pointY[index]]);
                    }else{
                        ponits.push([interpolate.x(t), interpolate.y(t)]);
                    }
                    
                    return generateLine(ponits);
                }
            }

            //点插值
            function getInterpolate(pointX, pointY){

                const domain = d3.range(0, 1, 1/(pointX.length-1));
                domain.push(1);

                const interpolateX = d3.scaleLinear()
                                        .domain(domain)
                                        .range(pointX);

                const interpolateY = d3.scaleLinear()
                                        .domain(domain)
                                        .range(pointY);
                return {
                    x: interpolateX,
                    y: interpolateY
                };

            }
    }

接下来渲染数据点,运用circle元素

/* ----------------------------渲染点------------------------  */
    chart.renderPonits = function(){
        let ponits = chart.body().selectAll('.point')
                    .data(data);
            
            ponits.enter()
                    .append('circle')
                    .classed('point', true)
                .merge(ponits)
                    .attr('cx', (d) => chart.scaleX(d.date))
                    .attr('cy', (d) => chart.scaleY(d.money))
                    .attr('r', 0)
                    .attr('fill', config.pointColor)
                    .attr('stroke', config.lineColor)
                    .attr('transform', 'translate(' + chart.scaleX.bandwidth()/2 +',0)')
                    .transition().duration(config.animateDuration)
                    .attr('r', config.pointSize);
    }

然后渲染坐标轴、文本标签、网格线等辅助组件,与柱状图类似

/* ----------------------------渲染坐标轴------------------------  */
    chart.renderX = function(){
        chart.svg().insert('g','.body')
                .attr('transform', 'translate(' + chart.bodyX() + ',' + (chart.bodyY() + chart.getBodyHeight()) + ')')
                .attr('class', 'xAxis')
                .call(d3.axisBottom(chart.scaleX));
    }

    chart.renderY = function(){
        chart.svg().insert('g','.body')
                .attr('transform', 'translate(' + chart.bodyX() + ',' + chart.bodyY() + ')')
                .attr('class', 'yAxis')
                .call(d3.axisLeft(chart.scaleY));
    }

    chart.renderAxis = function(){
        chart.renderX();
        chart.renderY();
    }

    /* ----------------------------渲染文本标签------------------------  */
    chart.renderText = function(){
        d3.select('.xAxis').append('text')
                            .attr('class', 'axisText')
                            .attr('x', chart.getBodyWidth())
                            .attr('y', 0)
                            .attr('fill', config.textColor)
                            .attr('dy', 30)
                            .text('日期');

        d3.select('.yAxis').append('text')
                            .attr('class', 'axisText')
                            .attr('x', 0)
                            .attr('y', 0)
                            .attr('fill', config.textColor)
                            .attr('transform', 'rotate(-90)')
                            .attr('dy', -40)
                            .attr('text-anchor','end')
                            .text('每日收入(元)');
    }

    /* ----------------------------渲染网格线------------------------  */
    chart.renderGrid = function(){
        d3.selectAll('.yAxis .tick')
            .each(function(d, i){
                if (config.ShowGridY.indexOf(d) > -1){
                    d3.select(this).append('line')
                        .attr('class','grid')
                        .attr('stroke', config.gridColor)
                        .attr('x1', 0)
                        .attr('y1', 0)
                        .attr('x2', chart.getBodyWidth())
                        .attr('y2', 0);
                }
            });

        d3.selectAll('.xAxis .tick')
            .each(function(d, i){
                if (config.ShowGridX.indexOf(d) > -1){
                    d3.select(this).append('line')
                        .attr('class','grid')
                        .attr('stroke', config.gridColor)
                        .attr('x1', 0)
                        .attr('y1', 0)
                        .attr('x2', 0)
                        .attr('y2', -chart.getBodyHeight());
                }
            });
    }

最后绑定鼠标交互事件,这里鼠标移动到点上时,会显示数值

/* ----------------------------绑定鼠标交互事件------------------------  */
    chart.addMouseOn = function(){
        //防抖函数
        function debounce(fn, time){
            let timeId = null;
            return function(){
                const context = this;
                const event = d3.event;
                timeId && clearTimeout(timeId)
                timeId = setTimeout(function(){
                    d3.event = event;
                    fn.apply(context, arguments);
                }, time);
            }
        }

        d3.selectAll('.point')
            .on('mouseover', function(d){
                const e = d3.event;
                const position = d3.mouse(chart.svg().node());
                e.target.style.cursor = 'hand'

                d3.select(e.target)
                    .attr('fill', config.textColor);
                
                chart.svg()
                    .append('text')
                    .classed('tip', true)
                    .attr('x', position[0]+5)
                    .attr('y', position[1])
                    .attr('fill', config.textColor)
                    .text('收入:' + d.money);
            })
            .on('mouseleave', function(){
                const e = d3.event;
                
                d3.select(e.target)
                    .attr('fill', config.pointColor);
                    
                d3.select('.tip').remove();
            })
            .on('mousemove', debounce(function(){
                    const position = d3.mouse(chart.svg().node());
                    d3.select('.tip')
                    .attr('x', position[0]+5)
                    .attr('y', position[1]-5);
                }, 6)
            );
    }

大功告成!!!


如果觉得这篇文章帮助了您,请打赏一个小红包鼓励作者继续创作哦!!!

在这里插入图片描述

D3 二维图表的绘制系列(三十)平行坐标系折线图 上一篇: 径向树图 代码结构和初始化画布的Chart对象介绍,请先看 这里 本图完整的源码地址: 这里 1 图表效果 2 数据 name,math,chinese,english,chemistry 小明,30,60,57,49 小红,50,95,65,65 小张,66,70,40,88 3 关键代码 导入数据 d3.csv('./data.csv', function(d){ ret... 阅读详情

相关推荐

D3 二维图表的绘制系列(七)堆叠面积图

上一篇: 基础折线图 https://blog.youkuaiyun.com/zjw_python/article/details/98210977 下一篇: 曲线图 https://blog.youkuaiyun.com/zjw_python/article/details/98201470 代码结构和初始化画布的Chart对象介绍,请先看 https://blog.youkuaiyun.com/zjw_python/articl...

zjw_python的博客 6066

D3基本图表绘制——折线图

制作折线图分成4步走: 1.首先划定制图区域和范围——画一个边框 2.数据处理得到绘制折线图需要的数据——绘制折线需要一个数组整体 3.画出x,y轴和折线——y轴绘制需要注意 4.补充标签,调节位置

m0_63150077的博客 5329

D3 二维图表的绘制系列(三十一)热力地图(heatMap.js)

上一篇: 平行坐标系折线图 代码结构和初始化画布的Chart对象介绍,请先看 这里 本图完整的源码地址: 这里 1 图表效果 2 数据 本文源码中提供了中国地图的GeoJson数据, 点击这里下载,如果想获取其他地区的数据,可参考这篇文章 3 关键代码 导入GeoJson格式的地图数据 d3.json('./china.json').then(function(data){ .... 一些简单...

zjw_python的博客 6768

使用 D3.js 进行简单的数据可视化--折线图

写在前面:大数据课程的作业之一是利用 D3.js 实现数据的可视化,下面记录一下简单的的实现 。 先附上程序(直接引入JSON文件的版本): 显示北京PM2.5的数值 //引入json数据,看下面解释    var data_DingLing = new Array(23);    var data_DongSi = new Array

小小学渣的博客 5630

备战数学建模3-MATLAB绘制各种二维图形

一、二维曲线及二维图形 1-plot(x,y)函数的基本用法 plot(x,y)函数的基本用法:其中分别用于存储x坐标和y的坐标。 我们看一下例子1,用plot函数绘制一条折线。代码如下: x = [2.5, 3.5, 4, 5] ; y = [1.5, 2.0, 1, 1.5] ; plot(x,y); 绘制的折线图如下所示: 如果plot()函数中只有参数x,则x作为纵坐标,x对应的位置作为横坐标。 如下代码的横坐标是1,2,3,4,纵坐标为向量x中的值。 x ...

nuist_NJUPT的博客 7835

d3-sample:使用 D3.js 示例多折线图和面积图

d3-样品 使用 D3.js 示例多折线图和面积图

d3.js学习10----折线图的制作

一切尽在注释中……………… ZheXian         var dataset=[5,3,1,5,2,4,2]; varxMarks=['Mon','Tues','Wed','Thur','Fri','Sat','Sun']; var w=600; var h=400; var title="Beijing"; var subTitl

Pitter_Patter_Bee的专栏 3392

企业级AI项目落地实战指南

企业级 AI 项目落地需构建“分阶段实施 + 多维度风控”的双轮驱动体系:实施端通过 POC 验证技术可行性、试点建立评估标准、规模化实现价值复制,各阶段需结合行业案例(如东阳光药、旺盈集团)提炼可复用经验;风险端则需覆盖技术(数据安全、模型稳定性)、合规(全球监管动态)、组织(人才与文化)维度,通过工具化框架(AI TRISM)与案例策略(邮储银行可解释性设计、拓斯达培训体系)实现风险可控。最终通过“场景聚焦 - 合规嵌入 - 持续优化”的循环机制,实现 AI 技术从“试点成功”到“全面价值创造”的跨越。

2509_93209761的博客 1437

D3---绘制折线图(数据列表形式)

一:要实现的效果 二:代码展示 1.需求分析 (1)数据以列表形式展示 var data=[[176.71,77.28,312.23,58.60, 119.62,179.52,458.55,359.68, 114.46,188.93,178.30 ,254.05], [437.77,153.76,347.83,190.85, 369.70,21...

qq_39579290的博客 3128

【原创,解决CLodop安装后无法调用的问题】已经安装过CLodop,但是网页上仍然提示“clodop云打印服务(localhost本地)未安装启动,点击这里执行安装....”

在某些国内web网站中,需要安装一个名为“CLodop”的插件;但在实际使用过程中,即使安装了CLodop插件,网页试图调用它时还是会提示“clodop云打印服务(localhost本地)未安装启动,点击这里执行安装...”,且无法完成相关打印任务 本文属原创博客,分析了解决CLodop无法被调用的问题,并附上了原理和解决方法,本质上是和跨域请求以及CORS类安全组策略相关

link_in_csdn的博客 2万+

VC Spyglass CDC验证避坑指南:如何正确配置同步复位信号(实验二重点解析)

本文深入解析VC Spyglass CDC验证中同步复位信号的正确配置方法,通过实验二案例详细展示错误配置的典型表现及修正过程。文章提供同步复位的最佳实践方案,包括约束文件修改指南、验证流程优化建议和高级调试技巧,帮助工程师有效避免CDC验证中的常见陷阱。

rock5的博客 678

利用D3.js(V4)绘制折线图(曲线图)

前言 D3.js是一个很优秀的可视化工具,也是一般的入门工具,可以和多种js和框架一同使用,可以有各种各样的操作。 这篇的代码借鉴了另一位大佬的代码。 学D3一个学期了,发现用的还是不是很6,打算写博客记录一下。 目录 如下所示,a.json是用的数据,index.css是主要的css文件,index.html是界面 数据 数据经过部分处理,这里就给一条吧。 只显示数据格式,非所用数据。 { "...

Sqssq的博客 3913

【Python爬虫】爬取企业专利信息

本来是个美好的周末的,但是周五晚上领导给了一个公司名称的Excel,让把这些公司的专利信息爬取下来。本文记录了爬取企业专利信息的心酸过程。码字不易,喜欢请点赞!!! 一、找寻目标网页 在接到这个任务之后,我的内心是拒绝的。但是又不能不干。因此首先我需要先找到有公司专利信息的地方。在一番查找和问了问朋友之后,我知道中国专利网、国家知识产权网、Incopat、天眼查、企查查这些网站上面都有企业的专利...

Asher117的博客 2万+

Matplotlib使用和绘制二维图表

目录 1 Matplotlib简介 1.1 什么是Matplotlib - 画二维图表的python库 1.2 为什么要学习Matplotlib - 画图 1.3 实现一个简单的Matplotlib画图 1.4 拓展知识点:Matplotlib三层结构 2 折线图(plot)与基础绘图功能 2.1 折线图绘制与保存图片 2.2 完善原始折线图(辅助显示层) 2.3 多个坐标系显示-plt.subplots(面向对象的画图方法) 2.4 折线图绘制函数图像 3 散点图(scatter) 4 柱状图(bar)

赵广陆 2647

Autosar Os降低CPU负载的方案总结

由于各个项目的实际场景不尽相同,可能需要有针对性的对症优化。如果你还有别的一些优化手段欢迎留言交流。

3678

详解YOLOv8网络结构/环境搭建/数据集获取/训练/推理/验证/导出/部署

YOLO(You Only Look Once)系列算法因其高效、准确等特点而备受瞩目。由2023年Ultralytics公司发布了YOLO的最新版本YOLOv8是结合前几代YOLO的基础上的一个融合改进版。本文YOLOv8网络结构/环境搭建/数据集获取/训练/推理/验证/导出/部署,从网络结构的讲解从模型的网络结构讲解到模型的部署都有详细介绍,同时在本专栏中还包括YOLOv8模型系列的改进包括个人提出的创新点,传统卷积、注意力机制、损失函数的修改教程,能够帮助你的论文获得创新点。

Snu77的博客 8万+

D3 二维图表的绘制系列(八)曲线图

上一篇: 堆叠面积图 https://blog.youkuaiyun.com/zjw_python/article/details/98214359 下一篇: 基础饼图 https://blog.youkuaiyun.com/zjw_python/article/details/98201470 代码结构和初始化画布的Chart对象介绍,请先看 https://blog.youkuaiyun.com/zjw_python/artic...

zjw_python的博客 3167

9篇2章2节:GBD 数据库的数据申请详解

无论您是初入公共卫生领域的学生、资深的科研工作者,还是政策决策者,GBD数据库都将成为您数据分析与决策支持中不可或缺的重要工具。

MD Code 2600

D3 二维图表的绘制系列(五)横向柱状图

上一篇: 堆叠柱状图 https://blog.youkuaiyun.com/zjw_python/article/details/98207916 下一篇: 基础折线图 https://blog.youkuaiyun.com/zjw_python/article/details/98201470 代码结构和初始化画布的Chart对象介绍,请先看 https://blog.youkuaiyun.com/zjw_python/arti...

zjw_python的博客 3263

AI辅助Android开发:从传统到智能化的技术演进

AI辅助开发的核心在于利用算法模型自动化或优化传统任务。在Android开发中,AI可应用于需求分析、设计、编码、测试和维护各阶段。需求分析:AI工具如基于NLP的模型(例如GPT系列)可解析用户需求文档,自动生成用户故事和原型设计。假设产品需求为“开发一个航班查询应用”,AI能提取关键词,输出UML图或伪代码。代码生成:使用AI代码助手(如GitHub Copilot),工程师输入自然语言描述,AI生成Java/Kotlin代码片段。

郑伟强dev的专栏 137

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Matplotlib可视化②——3D绘制散点图&曲面图&折线图&等高线图

一、3D折线图 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import random import matplotlib as mpl from matplotlib import cm from mpl_toolkits.mplot3d import axe...

cindy407的博客 5656

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

如何自学 D3

在数据可视化的世界中,D3 可谓极其耀眼的明星。 很多人着迷于 D3 那近乎无限可能的图形开发能力,而又被 D3 那海量的 API 所困住,往往学了很久却不得其道。 (还不了解 D3 的同学,可看《D3 vs G2 vs Echarts》) 下面,我以数据可视化开发为目的,说下我的 D3 入门路径: 一、学习 SVG D3 全名为 Data Drive Document,即通过 Data 操作 Document,而在做数据可视化时,Data 最常 Drive 的 Document 便是 SVG。 SV

u598975767的专栏 732

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Matplotlib之折线图与子图的绘制

一、Matplotlib简介 Matplotlib是一个Python 2D绘图库,可以生成各种硬拷贝格式和跨平台的交互式环境的出版物质量数据。Matplotlib可用于Python脚本,Python和IPython shell,Jupyter笔记本,Web应用程序服务器和四个图形用户界面工具包。 Matplotlib试图让简单的事情变得简单而艰难。只需几行代码即可生成绘图,直方图,功率谱,条形图...

weixin_42146366的博客 3410

备战数学建模1——MATLAB矩阵,二维图、三维图!(超级全面易懂)

创建一个三维曲面图,它是一个具有实色边和实色面的三维曲面。该函数将。[X,Y] = meshgrid(x,y) :基于向量x和y中包含的坐标返回二维网格坐标。X是一个矩阵,每一行是x的一个副本,Y也是一个矩阵,每一列是y的一个副本。坐标X和Y表示的网格有length(y)个行和length(x)个列。

惟愿一生无悔也无憾 1万+

MATLAB中画折线图:plot函数的简单用法

使用plot绘制二维图像 MATLAB中plot函数常常被用于绘制各种二维图像,其用法也是多种多样,本文仅介绍plot函数的基本用法——使用plot函数绘制二维点图和线图。plot函数的一般调用形式如下: plot(X, Y, LineSpec) 其中X由所有输入点坐标的x值组成,Y是由与X中包含的x对应的y所组成的向量。LineSpec是用户指定的绘图样式,主要选项如下: Specif...

亲亲Friends的博客 4万+
上一篇: D3 二维图表的绘制系列(五)横向柱状图
下一篇: D3 二维图表的绘制系列(七)堆叠面积图
PAT-python-zjw
博客等级 码龄10年 381粉丝 408原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值