微信小程序 canvas绘制雷达图

微信小程序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();

绘制出的雷达图如下所示


  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值