D3.js实现雷达图的方法详解

再简单介绍下D3.js,D3.js 是一个基于数据操作文档JavaScript库。D3帮助你给数据带来活力通过使用HTML、SVG和CSS。D3重视Web标准为你提供现代浏览器的全部功能,而不是给你一个专有的框架。结合强大的可视化组件和数据驱动方式Dom操作。这里也可以看到它是用SVG来呈现图表的,所以使用D3.js是需要一定的SVG基础的。

本文依然是先把简单的画图框架搭起来,添加SVG画布。这里和饼图有点类似,为了方便后面的绘制,我们把组合这些元素的g元素移动到画布的中心:

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>雷达图</title> <style> .container { margin: 30px auto; width: 600px; height: 300px; border: 1px solid #000; } </style> </head> <body> <div> <svg></svg> </div> <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> <script> window.onload = function() { var width = 600, height = 300; // 创建一个分组用来组合要画的图表元素 var main = d3.select('.container svg').append('g') .classed('main', true) .attr('transform', "translate(" + width/2 + ',' + height/2 + ')'); }; function getColor(idx) { var palette = [ '#2ec7c9', '#b6a2de', '#5ab1ef', '#ffb980', '#d87a80', '#8d98b3', '#e5cf0d', '#97b552', '#95706d', '#dc69aa', '#07a2a4', '#9a7fd1', '#588dd5', '#f5994e', '#c05050', '#59678c', '#c9ab00', '#7eb00a', '#6f5553', '#c14089' ] return palette[idx % palette.length]; } </script> </body> </html>

这里为什么我会说雷达图和饼图会有点类似呢?看一下下面这张图。

D3.js实现雷达图的方法详解

可以看到,雷达图的网轴(蓝色部分)是由多个正多边形所组成的,而正多边形的绘制正好是可以利用圆半径的特性来绘制的,所以从一开始把绘制的原点移动到画布的中心是很方便后面的绘制工作的。

模拟数据

我们先模拟一些原始数据。

var data = { fieldNames: ['语文','数学','外语','物理','化学','生物','政治','历史'], values: [ [10,20,30,40,50,60,70,80] ] };

计算网轴坐标并绘制

在前面的其他图表的实现中,都有比例尺或者布局这样的东西来为我们转化数据提供便利,雷达图是否也存在这样的工具函数呢?答案是没有!没有!没有!重要的事情说三遍!(-_-) 所以,我们只能开动自己的小脑瓜自己算了。

// 设定一些方便计算的常量 var radius = 100, // 指标的个数,即fieldNames的长度 total = 8, // 需要将网轴分成几级,即网轴上从小到大有多少个正多边形 level = 4, // 网轴的范围,类似坐标轴 rangeMin = 0, rangeMax = 100, arc = 2 * Math.PI; // 每项指标所在的角度 var onePiece = arc/total; // 计算网轴的正多边形的坐标 var polygons = { webs: [], webPoints: [] }; for(var k=level;k>0;k--) { var webs = '', webPoints = []; var r = radius/level * k; for(var i=0;i<total;i++) { var x = r * Math.sin(i * onePiece), y = r * Math.cos(i * onePiece); webs += x + ',' + y + ' '; webPoints.push({ x: x, y: y }); } polygons.webs.push(webs); polygons.webPoints.push(webPoints); }

计算网轴的坐标就是计算一个个多边形的各点坐标,为了后面添加polygon元素时方便绘制(points属性的赋值),我们需要在求点坐标的时候顺便把它们拼成字符串。上述代码的for循环中,外层循环代表一个多边形,内层循环代表多边形上的点,多边形与多边形之间差异仅仅在于它们的外圆的半径不同,而同一多边形的点与点之间的差异在于它们的角度不同。点的坐标由半径乘以角度的正弦或者余弦来求得。

得到了计算好的坐标以后,我们就开始添加网轴。

// 绘制网轴 var webs = main.append('g') .classed('webs', true); webs.selectAll('polygon') .data(polygons.webs) .enter() .append('polygon') .attr('points', function(d) { return d; });

添加一个g元素用来组合所有代表网轴的元素,选择其中的polygon元素并绑定polygons.webs数组,enter()搭配append()添加新的polygon元素,对points属性进行复制。完成这一系列在前面几篇文章中已经反复练习的操作以后,为了让网轴更加的明显,我们给它加一点样式。

.webs polygon { fill: white; fill-opacity: 0.5; stroke: gray; stroke-dasharray: 10 5; }

我们得到了如下图所示的网轴。

D3.js实现雷达图的方法详解

添加纵轴

接着我们把纵轴也添加上。纵轴就是添加一根根的线条,连接中心点和最外层的多边形上的点,需要的数据可以从polygons.webPoints[0]中取。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzjddp.html