参考文档: https://developers.weixin.qq.com/miniprogram/dev/component/canvas.html
const numCount = 3; // 元素个数 const numSlot = 4; // 一条线上的总节点数 const mW = 340; // Canvas的宽度 const mCenter = mW / 2; // 中心点 const mAngle = (Math.PI * 2) / numCount; // 角度 const mRadius = mCenter - 80; // 半径(减去的值用于给绘制的文本留空间) // 获取指定的Canvas let radCtx = null;
// 获取canvas 节点 getNodecanvas(valuedata) { radCtx = wx.createCanvasContext('radarCanvas', this(子组件中添加)); this.drawRadar(valuedata); },
// 雷达图 drawRadar(valdata) { // console.log(valdata) // 调用 this.drawArcEdge(); // 画圆 this.drawLinePoint(); // 设置数据 this.drawRegion(valdata, 'rgba(101, 163, 243, 1)'); // 设置文本数据 this.drawTextCans(valdata); // 设置节点 this.drawCircle(valdata, '#267EF0'); radCtx.draw(true, this.saveCanvasImage); }, // / 第一步:绘制5个圆,可以通过修改numSlot的数的大小,来确定绘制几个圆 drawArcEdge() { // radCtx.strokeStyle = "#E0E2E9" // radCtx.lineWidth = 1 //设置线宽 radCtx.setStrokeStyle('#E0E2E9'); radCtx.setLineWidth(1); // 设置线宽 for (let i = 0; i < numSlot; i++) { // 计算半径 radCtx.beginPath(); const rdius = (mRadius / numSlot) * (i + 1); // 计算每个圆的半径 // 画6条线段 for (let j = 0; j < numSlot; j++) { // 计算半径 radCtx.beginPath(); radCtx.arc(mCenter, mCenter, rdius, 0, 2 * Math.PI); // 开始画圆 // radCtx.stroke() } radCtx.closePath(); radCtx.stroke(); } }, // 绘制连接点 drawLinePoint() { radCtx.setLineDash([5, 10], 2); radCtx.beginPath(); for (let k = 0; k < numCount; k++) { const x = mCenter + mRadius * Math.cos(mAngle * k); const y = mCenter + mRadius * Math.sin(mAngle * k); radCtx.moveTo(mCenter, mCenter); radCtx.lineTo(x, y); } radCtx.stroke(); }, // 绘制数据区域(数据和填充颜色) drawRegion(mData, color) { radCtx.beginPath(); for (let m = 0; m < numCount; m++) { const x = mCenter + (mRadius * Math.cos(mAngle * m)) * (mData[m][1] / 100); const y = mCenter + (mRadius * Math.sin(mAngle * m)) * (mData[m][1] / 100); radCtx.lineTo(x, y); } radCtx.closePath(); radCtx.fillStyle = color; radCtx.fill(); }, // 绘制文字 drawTextCans(mData) { // radCtx.fillStyle = "#9B9B9B" radCtx.setFillStyle('#9B9B9B'); radCtx.font = 'bold 15px cursive'; // 设置字体 for (let n = 0; n < numCount; n++) { const x = mCenter + mRadius * Math.cos(mAngle * n); const y = mCenter + mRadius * Math.sin(mAngle * n); // radCtx.fillText(mData[n][0], x, y); // 通过不同的位置,调整文本的显示位置 if (mAngle * n >= 0 && mAngle * n <= Math.PI / 2) { radCtx.fillText(mData[n][0], x + 5, y + 5); } else if (mAngle * n > Math.PI / 2 && mAngle * n <= Math.PI) { radCtx.fillText(mData[n][0], x - radCtx.measureText(mData[n][0]).width - 7, y + 5); } else if (mAngle * n > Math.PI && mAngle * n <= (Math.PI * 3) / 2) { radCtx.fillText(mData[n][0], x - radCtx.measureText(mData[n][0]).width - 5, y); } else { radCtx.fillText(mData[n][0], x + 7, y + 2); } } }, // 画点 drawCircle(mData, color) { const r = 3; // 设置节点小圆点的半径 for (let i = 0; i < numCount; i++) { const x = mCenter + (mRadius * Math.cos(mAngle * i)) * (mData[i][1] / 100); const y = mCenter + (mRadius * Math.sin(mAngle * i)) * (mData[i][1] / 100); radCtx.beginPath(); radCtx.arc(x, y, r, 0, Math.PI * 2); radCtx.fillStyle = color; radCtx.fill(); } },// 转图片 saveCanvasImage() { const _this = this; setTimeout(() => { wx.canvasToTempFilePath({ canvasId: 'radarCanvas', // canvas: _this.canvas, success(res) { _this.setData({ canvasImg: res.tempFilePath, }); }, }); }, 700); },
注意1 最新版 只能在page 页面中画canvas 生效 在子组件中使用 要加this
注意2 生成图片的方法要加延时器 canvas画布是异步操作 重要 不然生成图有问题
注意3 canvas的画布和图片交替的时候 隐藏问题 利用定位 fixed absoulted 定位到显示区外面 不然不会根据画布生成图片