上一篇: 中国地图

下一篇: 日历热力图

代码结构和初始化画布的Chart对象介绍,请先看 这里

本图完整的源码地址:这里

1 图表效果

2 数据

{"data": [{"name": "组1","values": [850, 740, 900, 1070, 930, 850, 950, 980, 980, 880, 1000, 980, 930, 650, 760, 810, 1000, 1000, 960, 960]},{"name": "组2","values": [960, 940, 960, 940, 880, 800, 850, 880, 900, 840, 830, 790, 810, 880, 880, 830, 800, 790, 760, 800]},{"name": "组3","values": [880, 880, 880, 860, 720, 720, 620, 860, 970, 950, 880, 910, 850, 870, 840, 840, 850, 840, 840, 840]},{"name": "组4","values": [890, 810, 810, 820, 800, 770, 760, 740, 750, 760, 910, 920, 890, 860, 880, 720, 840, 850, 850, 780]},{"name": "组5","values": [890, 840, 780, 810, 860, 810, 790, 810, 820, 850, 870, 970, 810, 740, 810, 940, 950, 800, 890, 870]}]
}

3 关键代码

导入数据

d3.json('./data.json').then(function(data){.....

一些颜色样式配置

const config = {barPadding: 0.4,barStroke: 'red',margins: {top: 80, left: 80, bottom: 50, right: 80},textColor: 'black',gridColor: 'gray',tickShowGrid: [200,400,600,800,1000],title: '基础盒须图'}

数据处理,计算每组数据的中位数、上下四分位数以及最大最小值

/* -----------------------数据处理,计算中位数-------------------  */data = data.data;data.forEach((item) => {item.values.sort((a, b) => a-b);item.Q1 = d3.quantile(item.values, 0.25);item.Q2 = d3.quantile(item.values, 0.5);item.Q3 = d3.quantile(item.values, 0.75);item.min = item.values[0];item.max = item.values[item.values.length-1];});

尺度转换,与柱状图类似,区别在于注意Y轴的范围

/* ----------------------------尺度转换------------------------  */chart.scaleX = d3.scaleBand().domain(data.map((d) => d.name)).range([0, chart.getBodyWidth()]).padding(config.barPadding);chart.scaleY = d3.scaleLinear().domain([(Math.floor(d3.min(data.map((d) => d.min))/100)-1)*100, (Math.floor(d3.max(data.map((d) => d.max))/100)+1)*100]).range([chart.getBodyHeight(), 0])

使用rect元素渲染盒子,用line元素渲染线条

/* ----------------------------渲染盒子和须----------------------  */chart.renderBoxs = function(){let groups = chart.body().selectAll('.g').data(data);let groupsEnter = groups.enter().append('g').attr('class', 'g');groupsEnter.append('rect').attr('fill-opacity', '0').attr('stroke', config.barStroke);groupsEnter.each(function(){for (let i=0; i<5; i++){d3.select(this).append('line').attr('stroke', config.barStroke);}});let groupsUpdate = groupsEnter.merge(groups);groupsUpdate.selectAll('rect')      //绘制盒子矩形.attr('x', (d) => chart.scaleX(d.name)).attr('y', (d) => chart.scaleY(d.Q3)).attr('width', chart.scaleX.bandwidth()).attr('height', (d) => chart.scaleY(d.Q1) - chart.scaleY(d.Q3));groupsUpdate.each(function(d){       //绘制五条连接线let x1 = chart.scaleX(d.name);let x2 = x1 + chart.scaleX.bandwidth();let middle = (x1 + x2)/2;let minLine = {x1: x1,y1: chart.scaleY(d.min),x2: x2,y2: chart.scaleY(d.min)};let Q2Line = {x1: x1,y1: chart.scaleY(d.Q2),x2: x2,y2: chart.scaleY(d.Q2)};let maxLine = {x1: x1,y1: chart.scaleY(d.max),x2: x2,y2: chart.scaleY(d.max)};let linkLine1 = {x1: middle,y1: chart.scaleY(d.Q1),x2: middle,y2: chart.scaleY(d.min)};let linkLine2 = {x1: middle,y1: chart.scaleY(d.Q3),x2: middle,y2: chart.scaleY(d.max)};let lines = [minLine, Q2Line, maxLine, linkLine1, linkLine2];d3.select(this).selectAll('line').each(function(d,i){d3.select(this).attr('x1', lines[i].x1).attr('x2', lines[i].x2).attr('y1', lines[i].y1).attr('y2', lines[i].y2);});});groups.exit().remove();}

接下来,就是渲染坐标轴、网格以及文本标签等,与柱状图类似

/* ----------------------------渲染坐标轴------------------------  */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).ticks(5));}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('Group');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('Value');}/* ----------------------------渲染网格线------------------------  */chart.renderGrid = function(){d3.selectAll('.yAxis .tick').each(function(d){if (config.tickShowGrid.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);}});}

添加鼠标事件,鼠标悬停时,显示数据的中位数

/* ----------------------------绑定鼠标交互事件------------------------  */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('.g').on('mouseenter', function(d){const e = d3.event;const position = d3.mouse(chart.svg().node());e.target.style.cursor = 'hand';d3.select(e.target).attr('stroke-width', 2);chart.svg().append('text').classed('tip', true).attr('x', position[0]+5).attr('y', position[1]).attr('fill', config.textColor).text('median: ' + d.Q2);}).on('mouseleave', function(){const e = d3.event;d3.select(e.target).attr('stroke-width', 1);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 二维图表的绘制系列(十五)雷达图

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

  2. D3 二维图表的绘制系列(十四)气泡图

    上一篇: 多符号散点图 https://blog.csdn.net/zjw_python/article/details/98483989 下一篇: 雷达图 https://blog.csdn.net ...

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

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

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

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

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

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

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

    上一篇: 横向柱状图 https://blog.csdn.net/zjw_python/article/details/98209333 下一篇: 堆叠面积图 https://blog.csdn.ne ...

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

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

  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/98214359 下一篇: 基础饼图 https://blog.csdn.net ...

最新文章

  1. 为什么在定义hashcode时要使用31这个数呢
  2. The template root requires exactly one element.
  3. vmware安装ubuntu
  4. 苹果cms仿ZzzFun动漫视频站PC模板
  5. python爬虫爬取大众点评并导入redis
  6. css对于文字过长加省略号
  7. java 除以2_Java最快速的算出乘2 和除2的结果
  8. 考计算机一级用什么软件学,大学计算机一级考试用的是什么word软件
  9. android dpi 修改,DPI修改
  10. 图像灰度化的三种常见方法
  11. AD转换原理与方案设计(包含原理图、PCB和BOM表)
  12. 如何用软件测试固态颗粒,【英睿达 BX500固态硬盘使用总结】颗粒|读写速度|写入测试|建议_摘要频道_什么值得买...
  13. python判断负数_python中的负数
  14. element-ui校验表单只能输入数字
  15. 数据库学习笔记(进阶)
  16. 新建git分支(歪门邪道)
  17. Innovus零基础lab学习全面复盘总
  18. 申论公文题-宣传类-1
  19. SteamVR 2.x 手柄触摸3D物体(11)
  20. TabLayout的使用和自定义红点消息提示

热门文章

  1. Neo4j 4.0 / 4.1 配置快速参考 - 单服务器模式,适用于社区版和企业版
  2. 嵌入式之linux入门篇
  3. 【C语言编译器】01程序-编译器-IDE
  4. vue设置页面滚动高度_vue 解决无法设置滚动位置的问题
  5. MFC -- ShowWindow(int nCmdShow)参数总结
  6. socket连接超时问题
  7. urllib.request.Request的用法
  8. puts()和gets()
  9. EXCEL常用函数公式和VBA汇总
  10. 面试java工程师的自我介绍