# 浅谈canvas绘画王者荣耀--雷达图

SO，就想自己画一个canvas雷达图，顺便重新回顾一下canvas的知识点。

①正六边形

②数据填充区

③绘制文本

# 正六变形的坐标点解析

`bottom-center`坐标：`（250, 250 + 100）`

`bottom-left`坐标：`（250 - 100*sin(60°), 250+100*cos(60°)）`

`top-left`坐标：`（250 - 100*sin(60°), 250-100*cos(60°)）`

`top-center`坐标：`（250, 250 - 100）`

`top-right`坐标：`（250 + 100*sin(60°), 250-100*cos(60°)）`

`bottom-right`的坐标：`（250 + 100*sin(60°), 250+100*cos(60°)）`

`bottom-center`坐标：`（250 + 100*sin(0°), 250 + 100*cos(0°)）`

`bottom-left`坐标：`（250 + 100*sin(300°), 250+100*cos(300°)）`

`top-left`坐标：`（250 + 100*sin(240°), 250-100*cos(240°)）`

`top-center`坐标：`（250 +100*sin(180°), 250 + 100*cos(180°)）`

`top-right`坐标：`（250 + 100*sin(120°), 250-100*cos(120°)）`

`bottom-right`的坐标：`（250 + 100*sin60°), 250+100*cos(60°)）`

``var pointArr = [];for (var i = 0; i < 6; i++) {pointArr[i] = {};pointArr[i].x = 250 + 100 * Math.sin(60 * i);pointArr[i].y = 250 + 100* Math.cos(60 * i);``}``

# 1.1 绘画正六边形

``<style>canvas {display: block;width: 500px;height: 500px;}</style><body><canvas class="radar"></canvas></body><script>var canvas = document.getElementsByClassName('radar')[0];canvas.width = 500;canvas.height = 500;var ctx = canvas.getContext('2d');ctx.save();ctx.strokeStyle = '#888888'; // 设置线条颜色var lineArr = [];var rAngle = Math.PI * 2 / 6; // 算出每一个内角和console.log(rAngle);var rCenter = 250; // 确定中心点var curR = 100; // 确定半径长度ctx.beginPath();for (var i = 0; i < 6; i++) {lineArr[i] = {};lineArr[i].y = rCenter + curR * Math.cos(rAngle * i);lineArr[i].x = rCenter + curR * Math.sin(rAngle * i);ctx.lineTo(lineArr[i].x, lineArr[i].y);}ctx.closePath();ctx.stroke();``ctx.restore();``

# 1.2 绘画对角线

``ctx.strokeStyle = '#e8ddc7'; // PS吸管那么一吸ctx.save();ctx.beginPath();// for (var j = 0; j < 3; j++) {// ctx.lineTo(lineArr[j].x, lineArr[j].y);// ctx.lineTo(lineArr[j+3].x, lineArr[j+3].y);// ctx.stroke();// }for (var j = 0; j < 3; j++) {ctx.moveTo(lineArr[j].x, lineArr[j].y);ctx.lineTo(lineArr[j + 3].x, lineArr[j + 3].y);ctx.stroke();}ctx.closePath();``ctx.restore();``

# 2.1数据填充区

B等级看作区间 / 2, 那么A就是 区间 / 1.5.

``// 绘制数据区域var letterData = {'S': 1,'A': 1.5,'B': 2,'C': 2.5,'D': 3}ctx.save();ctx.beginPath();for (var i = 0; i < 6; i++) {lineArr[i].yEnd = rCenter + curR * Math.cos(rAngle * i) / (letterData[rData[i][1]]);lineArr[i].xEnd = rCenter + curR * Math.sin(rAngle * i) / (letterData[rData[i][1]]);ctx.lineTo(lineArr[i].xEnd, lineArr[i].yEnd);console.log(lineArr);}ctx.closePath();ctx.stroke();ctx.fillStyle = 'rgba(255, 0, 0, 0.5)';``ctx.fill();``

# 2.2 对数据填充区域绘画小圆点和边长

``ctx.lineWidth = 2; //设置数据填充区域的线条颜色ctx.strokeStyle = '#dd3f26'; //设置填充区域的颜色var point = 3; //设置数据填充区域的小圆点大小for (var i = 0; i < 6; i++) {ctx.beginPath();ctx.arc(lineArr[i].xEnd, lineArr[i].yEnd, point, 0, Math.PI * 2);ctx.fillStyle = 'rgba(255, 0, 0, 0.8)';ctx.fill();console.log(lineArr);}``ctx.restore();``

# 3.1 绘制文本

①用黑色16px字体绘制各点描述点

②用红色30px字体绘制各点能力级别

`` // 绘制文本var rData = [['生存', 'S'],['经济', 'S'],['输出', 'S'],['KDA', 'B'],['打野', 'B'],['推进', 'S']]ctx.save();ctx.font = '16px Microsoft Yahei'; //设置字体ctx.fillStyle = '#000'; // 颜色for (var i = 0; i < 6; i++) {var y = rCenter + curR * Math.cos(rAngle * i);var x = rCenter + curR * Math.sin(rAngle * i);ctx.fillText(rData[i][0], x, y);}``ctx.restore();``

# 3.2 绘制文本--描述

①如果`X轴` == 中心点，那么就判断`Y轴`。比中心点大文字下移一点，反之文字上移一点。

②如果`X轴` < 中心点，那么文字X轴位置就左移动一点,反正右移动距离。

`` // 绘制文本ctx.save();var fontSize = 16;ctx.font = fontSize + 'px Microsoft Yahei';ctx.textBaseline="middle"; //设置基线参考点ctx.textAlign="center"; // 文本居中ctx.fillStyle = '#000';for (var i = 0; i < 6; i++) {var y = rCenter + curR * Math.cos(rAngle * i);var x = rCenter + curR * Math.sin(rAngle * i);console.log(Math.sin(rAngle * i))var s_width = ctx.measureText(rData[i][0]).width; //获取当前绘画的字体宽度if ( x == rCenter) {if (y > rCenter ) {ctx.fillText(rData[i][0], x - s_width/2, y + fontSize);} else {ctx.fillText(rData[i][0], x - s_width/2, y - fontSize);}} else if ( x > rCenter) {console.log(rData[i][0]);ctx.fillText(rData[i][0], x + s_width*1.5, y);} else {ctx.fillText(rData[i][0], x - s_width*1.5, y);``}``

`ctx.textBaseline`: 设置或返回在绘制文本时使用的当前文本基线

`ctx.textAlign`: 这个文本水平居中，不过和CSS当中的居中不一样的是，他是从坐标点划出一条竖线分割文本的。

`ctx.measureText` : 返回包含指定文本宽度的对象。

# 3.2 绘制文本--能力级别

``// 绘制文本ctx.save();var fontSize = 16;var maxfontSize = 30;ctx.font = fontSize + 'px Microsoft Yahei';ctx.textBaseline="middle";ctx.textAlign="center";for (var i = 0; i < 6; i++) {var y = rCenter + curR * Math.cos(rAngle * i);var x = rCenter + curR * Math.sin(rAngle * i);console.log(Math.sin(rAngle * i))var s_width = ctx.measureText(rData[i][0]).width;if ( x == rCenter) {if (y > rCenter ) {ctx.fillText(rData[i][0], x - s_width/2, y + fontSize);} else {ctx.fillText(rData[i][0], x - s_width/2, y - fontSize);}} else if ( x > rCenter) {console.log(rData[i][0]);ctx.fillText(rData[i][0], x + s_width*1.5, y);} else {ctx.fillText(rData[i][0], x - s_width*1.5, y);}}ctx.restore();ctx.save();// 绘制等级ctx.font = '30px Microsoft Yahei bold';ctx.fillStyle = '#d7431f';ctx.textBaseline="middle";ctx.textAlign="center";for (var i = 0; i < 6; i++) {var y = rCenter + curR * Math.cos(rAngle * i);var x = rCenter + curR * Math.sin(rAngle * i);var M_width = ctx.measureText(rData[i][1]).width;if ( x == rCenter) {if (y > rCenter ) {ctx.fillText(rData[i][1], x + M_width/2, y + fontSize);} else {ctx.fillText(rData[i][1], x + M_width/2, y - fontSize);}} else if ( x > rCenter) {console.log(rData[i][0]);ctx.fillText(rData[i][1], x + M_width, y);} else {ctx.fillText(rData[i][1], x - M_width, y);}}ctx.restore();``ctx.save();``

Top