微信小程序 canvas绘制雷达图
发布时间
阅读量:
阅读量
微信小程序canvas画布中动态绘制雷达图的主要思路:
雷达图是以圆形形式呈现的一种数据可视化方法,在分析过程中将分隔线单独作为重点考察对象;该方法通过将圆形区域划分为四个扇区(分别对应θ_1=45^\circ、θ_2=135^\circ、θ_3=225^\circ和θ_4=315^\circ)来进行数据分布的展示与对比分析;每个扇区的范围分别为:第一部分为0至90度区间(不包含端点),第二部分为90至180度区间(不包含端点),第三部分为180至270度区间(不包含端点),第四部分则为270至360度区间(不包含端点)。
(2)数据集中的属性维度数量直接决定了各子维度在极坐标系中的分布位置,在圆形图中设定最大属性值(圆心半径)作为基准轴线长度后进行绘制操作,并标注每个维度对应的名称;随后通过三角函数计算各子维度对应的极坐标点位置。
(3)属性值直接决定了雷达图的形状,在绘制完成的雷达网上,每个属性值对应一个圆心角,并通过三角函数计算得到各点坐标后将这些点连接起来形成图形。
(4)定初始的属性的分支为刻度线,并标上刻度
在JavaScript代码中进行具体的实现可能会显得不够精细;然而绘制雷达图并不复杂,并且相对容易被理解。
wxml页面
<canvas class="canvas" canvas-id="radarcanvas" disable-scroll="false" />
AI写代码
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();
AI写代码
绘制出的雷达图如下所示
全部评论 (0)
还没有任何评论哟~
