微信小程序Canvas自绘图表之 仪表图(表盘)
微信小程序Canvas自绘图表之 仪表图(表盘)
大家好,我是梦辛工作室的灵,最近在开始画仪表图,一如既往的先看实现图:
实现代码如下:
function drawCircle(item, that) {//定义画图大小 let width = that.data.width * 0.7; let height = that.data.width * 0.7; //获取中心坐标 let centerPoint = { x: width / 2, y: height / 2 } let ctx = wx.createCanvasContext('circle'); ctx.save(); ctx.translate(width / 2, height / 2);//画布移动到中心 let each = 5; //每个线之间的间距度数 let len = 270 / each; //总共画270度 每次5度 需要画多少条线 let bili = 50 / 45; //比例 每一度代表多少值,用于画值 这里是 45度代表 50℃ let line = 30; //每根线的长度 let offset = 10; // 特殊度数的额外长度 let smallCircleWidth = 1.5; //小点的半径 let offsetCircle = 10;//小点距离线底部的距离 let astart = 99; let bstart = 52; let cstart = 161; let aend = 216; let bend = 54; let cend = 115; let aeach = (aend - astart) / len; let beach = (bend - bstart) / len; let ceach = (cend - cstart) / len; ctx.rotate(45 * Math.PI / 180); if(!item.curtemp){ item.curtemp = 125; } let pre = parseInt(item.curtemp / bili / each); //计算当前温度在第几根线 ctx.setLineWidth(2); for (let i = 0; i < len; i++) { if (i > pre) { ctx.setStrokeStyle("#E0E0E0"); } else { ctx.setStrokeStyle("rgb(" + (astart + i * aeach) + "," + (bstart + i * beach) + "," + (cstart + i * ceach) + ")"); } ctx.beginPath(); let point = { x: 0, y: centerPoint.y } let arrivePoint = { x: 0, y: point.y - line } if (i == len / 2) { point.y = centerPoint.y; } else { point.y = centerPoint.y - offset; } ctx.moveTo(point.x, point.y); ctx.lineTo(arrivePoint.x, arrivePoint.y); ctx.stroke(); ctx.setFillStyle("#F2F2F2"); ctx.beginPath(); ctx.arc(arrivePoint.x, arrivePoint.y - offsetCircle - smallCircleWidth, smallCircleWidth, 0, Math.PI * 2); ctx.fill(); ctx.rotate(each * Math.PI / 180); } ctx.restore(); //画字 let value = (item.curtemp + "") || "125"; let centerFontSize = 50; ctx.setFontSize(centerFontSize); ctx.setTextAlign("center"); ctx.setTextBaseline("middle"); ctx.setFillStyle("#000"); ctx.fillText(value, centerPoint.x, centerPoint.y); //画单位 let unitFontSize = 15; ctx.setFontSize(unitFontSize); ctx.setTextAlign("left"); ctx.setTextBaseline("top"); ctx.setFillStyle("#000"); ctx.fillText("℃", centerPoint.x + (value.length * centerFontSize / 3.5), centerPoint.y - centerFontSize / 2); unitFontSize = 10; ctx.setTextAlign("center"); ctx.setTextBaseline("middle"); ctx.setFillStyle("#CCCCCC"); ctx.setFontSize(unitFontSize); ctx.fillText(bili * 45 + "", line + offset + offsetCircle + smallCircleWidth * 2, centerPoint.y); ctx.setFontSize(unitFontSize); ctx.fillText(bili * 135 + "", centerPoint.x, line + offset + offsetCircle + smallCircleWidth * 2); ctx.setFontSize(unitFontSize); ctx.fillText(bili * 225 + "", centerPoint.x * 2 - (line + offset + offsetCircle + smallCircleWidth * 2), centerPoint.y); //画开启中 let stateStr = "未开启"; if (item.state) { ctx.setFillStyle("rgba(0,168,255,1)"); stateStr = "开启中"; } ctx.setFontSize(15); ctx.setTextAlign("center"); ctx.setTextBaseline("top"); ctx.fillText(stateStr, centerPoint.x, centerPoint.y + centerFontSize / 2); ctx.draw(); }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130wxml:
<view class="flex_column flex_center" style="height:20vh"> <text hidden="{{usetimestr.length == 0}}" class="text_hint">当前已使用</text> <text class="text_name">{{usetimestr}}</text> </view> <view style="width:100vw;height:50vh;" class="flex_column flex_center"> <canvas canvas-id="circle" style="width:70vw;height:70vw;"></canvas> </view> <view bindtap="doRefresh" class="btn_class">刷新</view> 12345678910
wxss:
/* pages/devdetail/devdetail.wxss */ page{ background: #fff; } .text_hint{ font-size:80%; font-family:PingFang SC; font-weight:500; color:rgba(204,204,204,1); } .text_name{ margin-top: 5px; font-size:100%; font-family:PingFang SC; font-weight:500; color:rgba(0,0,0,1); } .btn_class{ width:30vw; margin-top: 3vh; padding: 5vw; margin-left: 30vw; background:rgba(0,168,255,1); box-shadow:0px 10px 30px 0px rgba(0,168,255,0.4); border-radius:60px; color: #fff; text-align: center; }
12345678910111213141516171819202122232425262728293031322021年4月10日
应小伙伴的要求,增加了下触摸事件去实现如何通过触摸控制当前度数,下面是代码
先在xml上给canvas添加监听触摸事件
<canvas bindtouchmove="doTouchMove" bindtouchstart="doTouchStart" canvas-id="circle" style="width:70vw;height:70vw;"></canvas> 1
然后回到JS里面添加代码:
doTouchStart:function(res){ this.doTouchMove(res); }, //监听触发事件 doTouchMove:function(res){ let nowtime = (new Date()).getTime(); //100ms触发一次 减少不必要的绘图 if(nowtime - lasttime < 100){ return; } lasttime = nowtime; console.log(res); let x = res.touches[0].x; let y = res.touches[0].y; let width = app.globalData.width * 0.7; let height = app.globalData.width * 0.7; //获取中心坐标 let centerPoint = { x: width / 2, y: height / 2 } //刻度起点坐标 let startPoint = { x:centerPoint.x - centerPoint.x * Math.sin(Math.PI / 4), y:centerPoint.y + centerPoint.y * Math.cos(Math.PI / 4), } let line = 30; //每根线的长度 //最大圆的距离 let maxDistance = centerPoint.y; //最小圆的距离 let minDistance = centerPoint.y - line; //计算到圆心的距离 let distance = Math.sqrt(Math.pow(centerPoint.x - x,2) + Math.pow(centerPoint.y - y,2)); //触摸点再刻度上 if(distance <= maxDistance && distance >= minDistance){ //最大温度值 let maxTemp = 300; //当前触摸点与起点之间的夹角度数 let curtemp = 0; let offset = 0; //处理起点和终点,不显示区域问题 if(y > centerPoint.y){ if(x >= (startPoint.x + offset) && x < centerPoint.x){ curtemp = 0; drawCircle({curtemp },this); return; } else if (x <= (centerPoint.x * 2 - (startPoint.x + offset) ) && x > centerPoint.x){ curtemp = maxTemp; drawCircle({curtemp },this); return; } } //判断区域 let targetPoint = { x:0, y:0, angle:0, } if(x < startPoint.x && y > centerPoint.y){ //从左往右第一个区域 targetPoint.x = startPoint.x; targetPoint.y = startPoint.y; targetPoint.angle = 0; } else if (x < centerPoint.x && y < centerPoint.y){ //从左往右第二个区域 targetPoint.x = 0; targetPoint.y = centerPoint.y; targetPoint.angle = Math.PI / 4; } else if (x > centerPoint.x && y < centerPoint.y){ //从左往右第三个区域 targetPoint.x = centerPoint.x; targetPoint.y = 0; targetPoint.angle = (Math.PI * 3) / 4; } else if (x > centerPoint.x && y > centerPoint.y){ //从左往右第四个区域 targetPoint.x = centerPoint.x * 2; targetPoint.y = centerPoint.y; targetPoint.angle = (Math.PI * 5) / 4; } //计算玄长 let xuanDistance = Math.sqrt(Math.pow(targetPoint.x - x,2) + Math.pow(targetPoint.y - y,2)); //计算夹角 let jiaoDu = Math.asin((xuanDistance / 2) / centerPoint.y ) * 2 + targetPoint.angle; curtemp = ((jiaoDu / (Math.PI * 3 / 2)) * maxTemp).toFixed(0); drawCircle({curtemp },this); } }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108好啦,就可以实现触摸到哪里就显示那里的度数,简单吧
已将源码上传至github,传送门:https://github.com/wintton/YiBiaoCanvas
相关知识
微信小程序Canvas自绘图表之 仪表图(表盘)
微信小程序图表插件(wx
【微信小程序】wx
微信小程序中使用图表插件 wx
花店小程序|自助微信小程序开发平台之开发教程
网上花店微信小程序
Excel怎么做仪表图? Excel圆环图制作的经典图表分享
ppt怎么做交互式图表? 交互式PPT数据表盘教程
微信小程序后端怎么搭建
微信小程序插件
网址: 微信小程序Canvas自绘图表之 仪表图(表盘) https://www.huajiangbk.com/newsview1946915.html
上一篇: ER图设计与解析 |
下一篇: 【图形设计】用例图这样画,3步让 |
推荐分享

- 1君子兰什么品种最名贵 十大名 4012
- 2世界上最名贵的10种兰花图片 3364
- 3花圈挽联怎么写? 3286
- 4迷信说家里不能放假花 家里摆 1878
- 5香山红叶什么时候红 1493
- 6花的意思,花的解释,花的拼音 1210
- 7教师节送什么花最合适 1167
- 8勿忘我花图片 1103
- 9橄榄枝的象征意义 1093
- 10洛阳的市花 1039