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

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

代码结构和初始化画布的Chart对象介绍,请先看 https://blog.csdn.net/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 二维图表的绘制系列(六)基础折线图相关推荐

  1. D3 二维图表的绘制系列(一)介绍

    1 介绍 D3 (或者叫 D3.js )是一个基于 web 标准的 JavaScript 可视化库. D3 可以借助 SVG, Canvas 以及HTML 将你的数据生动的展现出来. D3 结合了强大 ...

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

    上一篇: 堆叠面积图 https://blog.csdn.net/zjw_python/article/details/98214359 下一篇: 基础饼图 https://blog.csdn.net ...

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

    上一篇: 基础折线图 https://blog.csdn.net/zjw_python/article/details/98210977 下一篇: 曲线图 https://blog.csdn.net/ ...

  4. D3 二维图表的绘制系列(二十六)盒须图

    上一篇: 中国地图 下一篇: 日历热力图 代码结构和初始化画布的Chart对象介绍,请先看 这里 本图完整的源码地址:这里 1 图表效果 2 数据 {"data": [{" ...

  5. D3 二维图表的绘制系列(二十二)桑基图sankey

    上一篇: 仪表盘图 https://blog.csdn.net/zjw_python/article/details/98596174 下一篇: 旭日图 https://blog.csdn.net/z ...

  6. D3 二维图表的绘制系列(十五)雷达图

    上一篇: 气泡图 https://blog.csdn.net/zjw_python/article/details/98485368 下一篇: 矩形树状图 https://blog.csdn.net/ ...

  7. D3 二维图表的绘制系列(二十七)日历热力图

    上一篇: 盒须图 下一篇: 弦图 代码结构和初始化画布的Chart对象介绍,请先看 这里 本图完整的源码地址: 这里 1 图表效果 2 数据 {"2018-01-01": 2,&q ...

  8. D3 二维图表的绘制系列(二十三)旭日图

    上一篇: 桑基图 https://blog.csdn.net/zjw_python/article/details/98611559 下一篇: 力导向图 https://blog.csdn.net/z ...

  9. D3 二维图表的绘制系列(二十)河流图

    上一篇: 封闭图 https://blog.csdn.net/zjw_python/article/details/98591118 下一篇: 仪表盘图 https://blog.csdn.net/z ...

最新文章

  1. mysql 7.4_CentOS 7.4 64位/ mysql
  2. GetLastError编号解释
  3. POJ 2010 Moo University - Financial Aid(堆维护滑窗kth,二分)
  4. mysql 使用 utf8mb4 编码
  5. 算法训练 字符串的展开
  6. 更改微信小程序的基础版本库;更改uni-app小程序基础库;更改用户的微信小程序基础库最低版本;设置用户的微信小程序版本库;
  7. Spring系列(六) Spring Web MVC 应用构建分析
  8. OSI七层模型详解 TCP/IP协议
  9. 配置SQL Server 2008 R2 Reporting Services
  10. PyTorch深度学习快速实战入门《pytorch-handbook》
  11. 弹性地基梁板的计算理论_龚晓南院士:30年创新实践,为地基处理开出“良方”...
  12. 解决电信网络Echarts官网打不开的问题
  13. 视觉跟踪的进展(Advances in Visual Tracking ) - 要饭的
  14. 童年经典,任天堂switch红白机游戏
  15. 走进小作坊(二十)----商道:胡雪岩叱咤商场的经营智慧
  16. kernel - regulator
  17. 用Python做了个图片识别系统(附源码)
  18. MathType怎么编辑等号带点
  19. kali2020.3安装openvas(gvm11)附gvm修改amdin密码以及gvm创建账号
  20. 关闭和打开445端口

热门文章

  1. Python中的KFold与StratifiedKFold
  2. 网络安全学习--域(二)
  3. 【启用rabbitmq遇到的问题全】command not found /Crash dump is being written to: erl_crash.dump...done
  4. 通过命令行方式远程连接redis
  5. 购物商城,规格选择,无货的规格置灰计算方法
  6. 视频跟踪算法--TLD跟踪算法介绍
  7. vscode 调试 python程序
  8. angular 阻止冒泡
  9. 感恩送书第1期:2019年快来了,感谢各位网友,送《Spring 5开发大全》
  10. 常见的RuntimeException异常