• QQ
  • nahooten@sina.com
  • 常州市九洲新世界花苑15-2

微信开发

常州微信小程序-canvas手绘雷达图

原创内容,转载请注明原文网址:http://homeqin.cn/a/wenzhangboke/jishutiandi/weixinkaifa/2019/0304/406.html

常州微信小程序-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坐标系是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>



上篇:上一篇:JS中深拷贝数组、对象、对象数组方法
下篇:下一篇:js数组的根本用法及数组依据下标(数值或字符)移