微信小程序canvas画布中动态绘制雷达图的主要思路:
(1)雷达图是在一个圆中绘制实现,将圆从圆心分成四部分,0-90,90-180,180-270,270-360(0),分界线单独拿出来考虑;
(2)数据的属性个数,决定雷达图的分支数,结合最大属性值(圆的半径)将雷达图属性线画出和属性名称标出,三角函数计算坐标;
(3)雷达图的属性值决定图形,在画好的雷达网状图中,根据各个属性值(圆的半径)用三角函数计算出坐标,并连成图;
(4)定初始的属性的分支为刻度线,并标上刻度
具体实现在js代码中,写的有点粗略,但是雷达图不是很难画的图,应该不难理解
wxml页面
<canvas class="canvas" canvas-id="radarcanvas" disable-scroll="false" />
js界面
//数据由上一页面传递过来,在页面onLoad函数中获得
//属性
var arrayQuality = new Array();
arrayQuality = options.qualityArray.split(',');
//属性值
var arrayScore = new Array();
arrayScore = options.scoreArray.split(',');
//画布
const ctx = wx.createCanvasContext('radarcanvas');
//属性数量
var len = arrayQuality.length;
//存储每个属性值坐标
var coordinatesArray = new Array(len);
//雷达图画维度线、维度线名称
ctx.setStrokeStyle('gray');
ctx.setFontSize(12);
for (var i = 0; i < len; i++) {
ctx.moveTo(150, 150)
if (2 * Math.PI * i / len == 0) {
ctx.lineTo(150, 10);
ctx.fillText(arrayQuality[i], 150 + 10, 10);
ctx.closePath();
ctx.stroke();
} else if (2 * Math.PI * i / len < Math.PI / 2) {
ctx.lineTo(150 - 140 * Math.sin(2 * Math.PI * i / len), 150 - 140 * Math.cos(2 * Math.PI * i / len));
ctx.fillText(arrayQuality[i], 150 - 140 * Math.sin(2 * Math.PI * i / len), 150 - 140 * Math.cos(2 * Math.PI * i / len));
ctx.closePath();
ctx.stroke();
} else if (2 * Math.PI * i / len == Math.PI / 2) {
ctx.lineTo(10, 150);
ctx.fillText(arrayQuality[i], 10, 150);
ctx.closePath();
ctx.stroke();
} else if (2 * Math.PI * i / len < Math.PI) {
ctx.lineTo(150 - 140 * Math.cos(2 * Math.PI * i / len - Math.PI / 2), 150 + 140 * Math.sin(2 * Math.PI * i / len - Math.PI / 2));
ctx.fillText(arrayQuality[i], 150 - 140 * Math.cos(2 * Math.PI * i / len - Math.PI / 2), 150 + 140 * Math.sin(2 * Math.PI * i / len - Math.PI / 2));
ctx.closePath();
ctx.stroke();
} else if (2 * Math.PI * i / len == Math.PI) {
ctx.lineTo(150, 290);
ctx.fillText(arrayQuality[i], 150, 290);
ctx.closePath();
ctx.stroke();
} else if (2 * Math.PI * i / len < 3 * Math.PI / 2) {
ctx.lineTo(150 + 140 * Math.sin(2 * Math.PI * i / len - Math.PI), 150 + 140 * Math.cos(2 * Math.PI * i / len - Math.PI));
ctx.fillText(arrayQuality[i], 150 + 140 * Math.sin(2 * Math.PI * i / len - Math.PI) - 10, 150 + 140 * Math.cos(2 * Math.PI * i / len - Math.PI));
ctx.closePath();
ctx.stroke();
} else if (2 * Math.PI * i / len == 3 * Math.PI / 2) {
ctx.lineTo(290, 150);
ctx.fillText(arrayQuality[i], 290 - 20, 150);
ctx.closePath();
ctx.stroke();
} else {
ctx.lineTo(150 + 140 * Math.cos(2 * Math.PI * i / len - 3 * Math.PI / 2), 150 - 140 * Math.sin(2 * Math.PI * i / len - 3 * Math.PI / 2));
ctx.fillText(arrayQuality[i], 150 + 140 * Math.cos(2 * Math.PI * i / len - 3 * Math.PI / 2) - 10, 150 - 140 * Math.sin(2 * Math.PI * i / len - 3 * Math.PI / 2));
ctx.closePath();
ctx.stroke();
}
}
/**雷达图画标准线 */
for (var m = 1; m <= 7; m++) {
ctx.moveTo(150, 150 - 20 * m)
for (var n = 0; n < len; n++) {
if (2 * Math.PI * n / len == 0) {
continue;
} else if (2 * Math.PI * n / len < Math.PI / 2) {
ctx.lineTo(150 - 20 * m * Math.sin(2 * Math.PI * n / len), 150 - 20 * m * Math.cos(2 * Math.PI * n / len));
} else if (2 * Math.PI * n / len == Math.PI / 2) {
ctx.lineTo(150 - 20 * m, 150);
} else if (2 * Math.PI * n / len < Math.PI) {
ctx.lineTo(150 - 20 * m * Math.cos(2 * Math.PI * n / len - Math.PI / 2), 150 + 20 * m * Math.sin(2 * Math.PI * n / len - Math.PI / 2));
} else if (2 * Math.PI * n / len == Math.PI) {
ctx.lineTo(150, 150 + 20 * m);
} else if (2 * Math.PI * n / len < 3 * Math.PI / 2) {
ctx.lineTo(150 + 20 * m * Math.sin(2 * Math.PI * n / len - Math.PI), 150 + 20 * m * Math.cos(2 * Math.PI * n / len - Math.PI));
} else if (2 * Math.PI * n / len == 3 * Math.PI / 2) {
ctx.lineTo(150 + 20 * m, 150);
} else {
ctx.lineTo(150 + 20 * m * Math.cos(2 * Math.PI * n / len - 3 * Math.PI / 2), 150 - 20 * m * Math.sin(2 * Math.PI * n / len - 3 * Math.PI / 2));
}
}
ctx.closePath();
ctx.stroke();
}
//雷达图维度线刻度
for (var i = 0; i <= 7; i++) {
ctx.fillText(i, 153, 150 - 20 * i - 2);
}
//雷达图每个维度打分点连线
ctx.beginPath();
ctx.setStrokeStyle('red');
ctx.setLineWidth(2);
ctx.moveTo(150, 150 - 20 * arrayScore[0])
for (var n = 0; n < len; n++) {
if (2 * Math.PI * n / len == 0) {
continue;
} else if (2 * Math.PI * n / len < Math.PI / 2) {
ctx.lineTo(150 - 20 * arrayScore[n] * Math.sin(2 * Math.PI * n / len), 150 - 20 * arrayScore[n] * Math.cos(2 * Math.PI * n / len));
} else if (2 * Math.PI * n / len == Math.PI / 2) {
ctx.lineTo(150 - 20 * arrayScore[n], 150);
} else if (2 * Math.PI * n / len < Math.PI) {
ctx.lineTo(150 - 20 * arrayScore[n] * Math.cos(2 * Math.PI * n / len - Math.PI / 2), 150 + 20 * arrayScore[n] * Math.sin(2 * Math.PI * n / len - Math.PI / 2));
} else if (2 * Math.PI * n / len == Math.PI) {
ctx.lineTo(150, 150 + 20 * arrayScore[n]);
} else if (2 * Math.PI * n / len < 3 * Math.PI / 2) {
ctx.lineTo(150 + 20 * arrayScore[n] * Math.sin(2 * Math.PI * n / len - Math.PI), 150 + 20 * arrayScore[n] * Math.cos(2 * Math.PI * n / len - Math.PI));
} else if (2 * Math.PI * n / len == 3 * Math.PI / 2) {
ctx.lineTo(150 + 20 * arrayScore[n], 150);
} else {
ctx.lineTo(150 + 20 * arrayScore[n] * Math.cos(2 * Math.PI * n / len - 3 * Math.PI / 2), 150 - 20 * arrayScore[n] * Math.sin(2 * Math.PI * n / len - 3 * Math.PI / 2));
}
}
ctx.closePath();
ctx.stroke();
ctx.draw();
绘制出的雷达图如下所示