Web前端之路微信小程序开发实战Web前端之路

微信小程序canvas手绘雷达图

2017-03-19  本文已影响336人  掌雄

微信小程序已经发布了两个多月了,没有想象中那么火。但是一些拥有多用户量的APP应用也会抽出主业务流程做微信小程序版本。做过小程序开发的小伙伴们都知道微信小程序缺少类似echart.js的图形库,然而业内echart.js等主流的h5图形库并不能在小程序上运行,所以遇到绘制图形需求的时候我们只能用canvas绘画。本文为大家分享的是以自定义组件的形式绘制雷达图。

雷达图

自定义组件

(1)建立组件文件

在工程根目录建立component文件夹,里面建radar目录,在radar里面建radar.js、radar.wxml、radar.wxss,3个文件


radar.js写一个导出的方法:
<pre>
module.exports = {
radar
};
</pre>

radar.wxml写一个模板:
<pre>
<template name="radar">
<view class="radar">
<canvas class="canvas" canvas-id="radarCanvas" />
</view>
</template>
</pre>

radar.wxss写对应的样式:
<pre>
.radar canvas {
width: 750rpx;
height: 750rpx;
background-color: #6fb9de;
}
</pre>

(2)在页面中引入组件

比如我们要在index页面引入组件,先在index.wxss引入样式文件:
<pre>
@import "../../component/radar/radar.wxss"
</pre>

在index.wxml引入模板文件:
<pre>

<import src="../../component/radar/radar.wxml"/>

<template is="radar"/>
</pre>

在index.js引入js逻辑文件:
<pre>
// 1 引入雷达图
import { radar } from '../../component/radar/radar'
// 2 page对象里加入组件
Page({
radar,
// 3 在onLoad函数里面调用组件
onLoad: function () {
this.radar.draw('');
}
</pre>

雷达图组件的具体实现

(1)确定坐标系与中心点
canvas坐标系

canvas坐标系是X轴向右增加,Y轴向下增加的。

确定中心点:
<pre>
centerPoint = [rpx(375), rpx(375)];
context.moveTo(centerPoint[0], centerPoint[1]);
</pre>

根据雷达图要分的比例项(即雷达图的角数)、网状每一环的宽度、直角三角形的正弦sin计算网状点的Y轴坐标,直角三角形的正弦cos计算网状点的X轴坐标

网状点的Y轴坐标(直角三角形的对角边) = sin角度 x 网状每一环的宽度(直角三角形的斜边)
网状点的X轴坐标(直角三角形的邻角边) = cos角度 x 网状每一环的宽度(直角三角形的斜边)

<pre>
for(n = 0; n < layerNum; n++) {
layerPoints[n] = [];
for(k = 0; k < angleNum; k++) {
context.moveTo(centerPoint[0], centerPoint[1]);
let offsetX = layerWidth * (n + 1) * getXParam(angleAvg * (k + 1) + angleOffset);
let offsetY = layerWidth * (n + 1) * getYParam(angleAvg * (k + 1) + angleOffset);
let distX = centerPoint[0] + offsetX;
let distY = centerPoint[1] + offsetY;
if(n == layerNum - 1) {
context.lineTo(distX, distY);
if(wordArr[k]) {
let wordOffsetX = offsetX >= 0 ? 1 : -1;
wordOffsetX = distX + wordOffsetX * wordOffset[k][0];
let wordOffsetY = offsetY >= 0 ? 1 : -1;
wordOffsetY = distY + wordOffsetY * wordOffset[k][1];
context.fillText(wordArr[k], wordOffsetX, wordOffsetY);
}
}
layerPoints[n][k] = [distX, distY];
}
}
</pre>

根据角度数来返回计算结果坐标偏移量的正负,是x轴是在左还是右,y轴是上还是下:
<pre>
let getXParam = (angle) => {
let param = 1;
if(angle >= 0 && angle < 90) {
param = 1;
} else if(angle >= 90 && angle < 180) {
param = -1;
angle = 180 - angle;
} else if(angle >= 180 && angle < 270) {
param = -1;
angle = angle - 180;
} else if(angle >= 270 && angle <= 360) {
param = 1;
angle = 360 - angle;
}

let angleCos = Math.cos(Math.PI / 180 \* angle);
if(angleCos < 0) {
    angleCos = angleCos \* -1;
}
return angleCos \* param;

};

let getYParam = (angle) => {
let param = 1;
if(angle >= 0 && angle < 90) {
param = 1;
} else if(angle >= 90 && angle < 180) {
param = 1;
angle = 180 - angle;
} else if(angle >= 180 && angle < 270) {
param = -1;
angle = angle - 180;
} else if(angle >= 270 && angle <= 360) {
param = -1;
angle = 360 - angle;
}

let angleSin = Math.sin(Math.PI / 180 \* angle);
if(angleSin < 0) {
    angleSin = angleSin \* -1;
}
return angleSin \* param;

};
</pre>

计算完网状交点后,用context.moveTo把对应的点连起来就可以了,最后把数据在上面显示,即把比例点连接成一个封闭图形填充一个办透明的颜色就可以了:

<pre>
// 绘制的雷达比例数据
let dataArr = [5, 2, 6, 2, 6, 0, 3];
// 绘制比例:
context.beginPath();
context.setStrokeStyle("rgba(77,168,213,0.85)");
context.setFillStyle("rgba(77,168,213,0.85)");

    let isFirstPoint = true;
    let tmpPoints = [];
    for(m = 0; m < angleNum; m++) {
        tmpPoints = centerPoint;
        if(dataArr[m] > 0) {
            for(n = 0; n < layerNum; n++) {
                if(dataArr[m] == (n + 1)) {
                    tmpPoints = layerPoints[n][m];
                    break;
                }
            }
        }
        if(isFirstPoint) {
            context.moveTo(tmpPoints[0], tmpPoints[1]);
            isFirstPoint = false;
        } else {
            context.lineTo(tmpPoints[0], tmpPoints[1]);
        }
    }

    context.fill();
    context.stroke();
    context.closePath();

</pre>

最终效果图

微信小程序雷达图完整代码:
https://github.com/zhangxiongwu/smallAppRadar

结语:熟悉绘画canvas与计算坐标点可以绘画很多定制化需求的图形。

您的意见是我改善的东西,欢迎评论提建议,如果对您有帮助,请点个赞,谢谢~~
菲麦前端专题,汇聚前端好文,邀您关注!

上一篇下一篇

猜你喜欢

热点阅读