利用Canvas绘制雷达图
2017-10-27 21:32
866 查看
雷达图(蜘蛛网图)是一种常见的数据分析图表,本文采用canvas来绘制雷达图,并最终封装成一个小组件。首先来看一下最终的效果图:
![](https://img-blog.csdn.net/20171030210654206)
![](https://img-blog.csdn.net/20171030122210045)
下面进行具体的代码实现。
效果如下:
![](https://img-blog.csdn.net/20171030172424334)
效果如下:
![](https://img-blog.csdn.net/20171030205617852)
效果入下:
![](https://img-blog.csdn.net/20171030210122253)
最终效果图:
![](https://img-blog.csdn.net/20171030210654206)
调用:
如何画正多边形
以正五边形雷达图为例(其他任意正多边形也一样),如下图所示。Canvas画图的原点在左上角,以r为半径,
(r, r)为圆心作圆,作为正五边形的外接圆,则正五边形每条边所对应的圆心角均为
rad = 2*Math.PI/5。再根据正余弦可以求得每个定点所对应的坐标,这样一个正五边形就可以画出来了。
下面进行具体的代码实现。
HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Canvas绘制雷达图</title> <style> body, html, div{ margin: 0; padding: 0; } .container { width: 300px; height: 300px; margin: 50px auto; } </style> </head> <body> <div class="container" id="container"></div> </body> </html>
基本样式和模拟数据
var container = document.getElementById('container'); var cans = document.createElement("canvas"); container.appendChild(cans); var ctx = cans.getContext("2d"); var data = [["HTML", 0.5], ["CSS", 0.6], ["JS", 0.4], ["jQuery", 0.8], ["React", 0.7]]; cans.width = 300; cans.height = 300; var step = data.length; var r = 150;
绘制背景网格
将正五边形从内到外分成十份,并以蓝白相间的背景进行填充。//绘制网格背景 var isBlue = false; for(var s = 10; s > 0; s--) { ctx.beginPath(); for(var i=0;i<step;i++) { var rad = 2*Math.PI/step * i; var x = r + Math.sin(rad)*r*(s/10); var y = r + Math.cos(rad)*r*(s/10); ctx.lineTo(x, y); } ctx.closePath(); ctx.fillStyle = (isBlue = !isBlue)?'#99c0ff' : '#f1f9ff'; ctx.fill(); }
效果如下:
绘制伞骨
由于项目名称是定位在五边形的顶点处,因此,在绘制伞骨的同时可以把每个项目的名称同时绘制出来。//绘制伞骨 ctx.beginPath(); for(var i=0;i<step;i++) { var rad = 2*Math.PI/step * i; var x = r + Math.sin(rad)*r; var y = r + Math.cos(rad)*r; ctx.moveTo(r,r); ctx.lineTo(x, y); var text = document.createElement("div"); text.innerHTML = data[i][0]; text.style.position = "absolute"; //添加文本 if(x > r) { text.style.left = ( x + 10) + 'px'; } else { text.style.right = (300-x +5) + 'px'; } if(y > r) { text.style.top = y + 'px'; } else { text.style.bottom = (300 - y) + 'px'; } container.appendChild(text); } ctx.strokeStyle = "#e0e0e0" ctx.stroke();
效果如下:
绘制数据点
ctx.fillStyle = "#ff7676"; for(var i=0;i<step;i++) { var rad = 2*Math.PI/step * i; var x = r + Math.sin(rad)*r*data[i][1]; var y = r + Math.cos(rad)*r*data[i][1]; ctx.beginPath(); ctx.arc(x,y,4,0,2*Math.PI); ctx.fill(); ctx.closePath(); }
效果入下:
绘制折线
ctx.strokeStyle = "#f00"; ctx.beginPath(); for(var i=0;i<step;i++) { var rad = 2*Math.PI/step * i; var x = r + Math.sin(rad)*r*data[i][1]; var y = r + Math.cos(rad)*r*data[i][1]; ctx.lineTo(x,y); } ctx.closePath(); ctx.stroke();
最终效果图:
封装插件
完整插件代码://radar.js
(function() {
var Radar = function(cfg) {
var outContainer = document.querySelector(cfg.el);
var container = document.createElement("div");
var cans = document.createElement("canvas");
container.appendChild(cans);
outContainer.appendChild(container);
var ctx = cans.getContext("2d");
var data = cfg.data;
var w = cfg.width;
var h = cfg.height;
container.style.position = "relative";
container.style.width = w+"px";
container.style.height = h+"px";
cans.width = w;
cans.height = h;
var step = data.length;
var r = w/2;
//绘制网格背景
var isBlue = false;
for(var s = 10; s > 0; s--) {
ctx.beginPath();
for(var i=0;i<step;i++) {
var rad = 2*Math.PI/step * i;
var x = r + Math.sin(rad)*r*(s/10);
var y = r + Math.cos(rad)*r*(s/10);
ctx.lineTo(x, y);
}
ctx.closePath();
ctx.fillStyle = (isBlue = !isBlue)?'#99c0ff' : '#f1f9ff';
ctx.fill();
}
//绘制伞骨
ctx.beginPath();
for(var i=0;i<step;i++) {
var rad = 2*Math.PI/step * i;
var x = r + Math.sin(rad)*r;
var y = r + Math.cos(rad)*r;
ctx.moveTo(r,r);
ctx.lineTo(x, y);
var text = document.createElement("div");
text.innerHTML = data[i][0];
text.style.position = "absolute";
//添加文本
if(x > r) {
text.style.left = ( x + 10) + 'px';
} else {
text.style.right = (w-x +5) + 'px';
}
if(y > r) {
text.style.top = y + 'px';
} else {
text.style.bottom = (h - y) + 'px';
}
container.appendChild(text);
}
ctx.strokeStyle = "#e0e0e0"
ctx.stroke();
//绘制折线
ctx.strokeStyle = "#f00"; ctx.beginPath(); for(var i=0;i<step;i++) { var rad = 2*Math.PI/step * i; var x = r + Math.sin(rad)*r*data[i][1]; var y = r + Math.cos(rad)*r*data[i][1]; ctx.lineTo(x,y); } ctx.closePath(); ctx.stroke();
//添加数据点
ctx.fillStyle = "#ff7676"; for(var i=0;i<step;i++) { var rad = 2*Math.PI/step * i; var x = r + Math.sin(rad)*r*data[i][1]; var y = r + Math.cos(rad)*r*data[i][1]; ctx.beginPath(); ctx.arc(x,y,4,0,2*Math.PI); ctx.fill(); ctx.closePath(); }
}
window["Radar"] = Radar;
})();
调用:
var radar = new Radar({ el: "#container", width: 300, height: 300, data: [["HTML", 0.5], ["CSS", 0.6], ["JS", 0.9], ["jQuery", 0.8], ["React", 0.7]] });
总结
到现在为止,整个雷达图就绘制完毕。当然还可以添加更多的内容,比如文字颜色,动画等。文字颜色可以在data数组中添加,给每一项再增加一个颜色项。动画的话可以将数据点和折线部分提出来单独绘制一个图层,通过控制数据点的大小实现图形的生长动画。完整版参加github:https://github.com/materialcoder/Chart-Component相关文章推荐
- 利用Android的Canvas绘制正弦函数图像
- html5学习笔记二:利用canvas绘制简单图形
- qml学习---------------利用Canvas绘制文本
- 利用canvas进行一个饼形图的绘制
- 利用canvas绘制饼状图一种方法
- 利用canvas绘制粒子效果
- Android开发:ImageView上绘制旋转圆环(透明度不同的旋转圆环,利用canvas.drawArc实现)
- qml学习--------------利用Canvas绘制图片
- 利用canvas实现折线图的绘制
- 利用Html 5的canvas标签绘制水流和水池动画
- HTML5利用canvas绘制太极图案
- ImageView上绘制旋转圆环(透明度不同的旋转圆环,利用canvas.drawArc实现) .
- 微信小程序 canvas绘制雷达图
- Android编程开发之在Canvas中利用Path绘制基本图形(圆形,矩形,椭圆,三角形等)
- 利用canvas绘制签名
- Android软件开发:在Canvas中利用Path绘制基本图形
- 利用canvas绘制折线图的一种方法
- HTML5 JS Canvas利用贝塞尔曲线绘制圆角矩形
- js 利用canvas绘制直线、曲线
- android中利用Canvas绘制折线图