最近小程序很火,博主作为新人也去了解一下,发现小程序的确有其优势之处,就是还不是很完善,当然这是一个新的东西免不了存在各种问题,相信以后问题会减少。
正文开始。
在学习过程中我用微信canvas去画了一个雷达图,嘛,毕竟图形才是直观的数据体现。
博主是采用的微信自主研发的类vue框架wepy来进行开发的,如果有不了解wepy的小伙伴可以去腾讯的wepy官方文档看看,较之原生的小程序框架还是有许多优点的。
首先是确定canvas包括canvas的尺寸,微信小程序的canvas标签默认宽度为300px,高度为225px。
<
style
>
.radar-canvas {
width:
750rpx;
height:
650rpx;
}
style
>
<
template
>
<
view
>
<
canvas
class=
"radar-canvas"
canvas-id=
"radarCanvas"
disable-scroll=
"false"
/>
view
>
template
>
然后是确定雷达图的中心坐标,这里可以直接获取当前屏幕的宽,然后除以2就是X坐标。Y坐标可以自行调整。
var windowW =
wx.
getSystemInfoSync().
windowWidth;
var centerPointX = windowW /
2;
var centerPointY = centerPointX;
接着开始建立一些需要的雷达图数据。
data = {
radius: centerPointX -
this.
rpx(
200),
//半径,减去的部分为文字留空位
radarData: [
{desc:
"动漫",value:
"0.6"},
{desc:
"体育",value:
"0.5"},
{desc:
"旅游",value:
"0.8"},
{desc:
"游戏",value:
"0.5"},
{desc:
"学习",value:
"0.3"}
]
};
现在开始写方法
第一步:画出多边形,边数根据radarData的长度来确定。
//draw polygon
drawPolygon(
ctx,
sideNum,
angle) {
ctx.
setStrokeStyle(
"rgb(83,139,81)");
var r =
this.
radius /
5;
//单位半径
for (
var i =
1; i <
5; i++) {
ctx.
beginPath();
var currR = r * (i +
1);
//当前半径
for (
var j =
0; j < sideNum; j++) {
var x = centerPointX + currR *
Math.
cos(angle * j +
Math.PI /
3.3);
//Math.PI/3.3是为了调整图形的偏移量,可自行设置
var y = centerPointY + currR *
Math.
sin(angle * j +
Math.PI /
3.3);
ctx.
lineTo(x, y);
}
ctx.
setLineDash([
2,
2]);
//虚线
ctx.
closePath();
ctx.
stroke();
}
}
第二步:绘制伞骨。
//draw rib
drawRib(
ctx,
sideNum,
angle) {
ctx.
setStrokeStyle(
"#cdcdcd");
ctx.
beginPath();
for (
var i =
0; i < sideNum; i++) {
var x = centerPointX +
this.
radius *
Math.
cos(angle * i +
Math.PI /
3.3);
var y = centerPointY +
this.
radius *
Math.
sin(angle * i +
Math.PI /
3.3);
ctx.
moveTo(centerPointX, centerPointY);
ctx.
lineTo(x, y);
}
ctx.
closePath();
ctx.
stroke();
}
第三步:添加radar各方向的文字描述。
//add radar description
addTags(
ctx,
radarData,
sideNum,
angle) {
ctx.
setFontSize(
this.
rpx(
30));
ctx.
setFillStyle(
"rgb(95, 153, 32)");
//确定文本位置,可以根据微信小程序文档中的具体方法来设置
for (
var i =
0; i < sideNum; i++) {
var x =
parseInt(
centerPointX +
this.
radius *
Math.
cos(angle * i +
Math.PI /
3.3)
);
var y =
parseInt(
centerPointY +
this.
radius *
Math.
sin(angle * i +
Math.PI /
3.3)
);
var center =
parseInt(centerPointX);
var centerY =
parseInt(centerPointY);
if (x < center && y < centerY) {
ctx.
setTextAlign(
"left");
ctx.
fillText(radarData[i].
desc, x -
this.
rpx(
120), y);
}
else
if (x -
this.
rpx(
20) > center && y < centerY) {
ctx.
setTextAlign(
"right");
ctx.
fillText(radarData[i].
desc, x +
this.
rpx(
120), y);
}
else
if (y > centerY) {
ctx.
setTextAlign(
"center");
ctx.
fillText(radarData[i].
desc, x, y +
this.
rpx(
80));
}
else {
ctx.
setTextAlign(
"center");
ctx.
fillText(radarData[i].
desc, x, y -
this.
rpx(
40));
}
}
}
第四步:绘制数据点。
//add dataPoint
addDataPoint(
ctx,
radarData,
sideNum,
angle) {
for (
var i =
0; i < sideNum; i++) {
var x = centerPointX +
this.
radius *
Math.
cos(angle * i +
Math.PI /
3.3) * radarData[i].
value;
var y = centerPointY +
this.
radius *
Math.
sin(angle * i +
Math.PI /
3.3) * radarData[i].
value;
ctx.
beginPath();
ctx.
arc(x, y,
3,
0,
2 *
Math.PI);
ctx.
setFillStyle(
"rgb(0, 91, 51)");
ctx.
fill();
ctx.
closePath();
}
}
第五步:连线并填充区域。
//line point
linePoint(
ctx,
radarData,
sideNum,
angle) {
ctx.
setStrokeStyle(
"rgb(83, 139, 81)");
ctx.
beginPath();
for (
var i =
0; i < sideNum; i++) {
var x =
centerPointX +
this.
radius *
Math.
cos(angle * i +
Math.PI /
3.3) * radarData[i].
value;
var y =
centerPointY +
this.
radius *
Math.
sin(angle * i +
Math.PI /
3.3) * radarData[i].
value;
ctx.
lineTo(x, y);
}
ctx.
closePath();
ctx.
setFillStyle(
"rgba(0,91,51,0.2)");
//填充色
ctx.
fill();
//填充
ctx.
stroke();
}
最后看看效果
附完整代码:
github链接。
学习之后留下笔记,后续将会有更多的其它chart。
新人菜鸟第一次写,如果有错误希望各位指出,谢谢。