使用canvas绘制简单的仪表盘

1 篇文章 0 订阅
1 篇文章 0 订阅

canvas绘制仪表盘
canvas绘制仪表盘
本案例简单的封装了一个仪表盘,用户可以在函数中传递仪表盘数据,刻度盘、颜色相关配置。
详细代码如下,可复制在html文档中浏览器直接运行

<!DOCTYPE html>
<body>
  <div>
    <h3>仪表盘1</h3>
    <canvas id="myCanvas1" width="900" height="300">
      你的浏览器不支持canvas,请升级你的浏览器
    </canvas>
    <h3>仪表盘2</h3>
    <canvas id="myCanvas2" width="900" height="300">
      你的浏览器不支持canvas,请升级你的浏览器
    </canvas>
  </div>
  <script>
    /* 绘制仪表盘样式1 */
			function initCanvasYbp1(opts = {}) {
				var canvasId = opts['id'] || 'myCanvas1'
				var data = opts['data'] || 100 // 值
				var center_data_font = '30px Arial'
				var formatStr = opts['formatStr'] || '/限55'
				var splitNumber = opts['splitNumber'] || 5 // 刻度数量
				var max = opts['max'] || 160 // 最大值
				var min = opts['min'] || 0 // 最小值
				var circle_width = 26 // 仪表盘边宽
				var startAngle = 0.8 // 开始角度
				var endAngle = 2.2 // 结束角度
				var splitColor = '#ffffff' // 刻度线颜色
				var splitWidth = 2 // 刻度线宽度
				var offset_split_text = opts['offsetSplitText'] || [-10, -10, -12, -20, -20] // 刻度文本偏移
				var split_text_font = '14rpx Arial'
				var circle = { // 定义圆
            x: 200,
            y: 150,
            radius: 100
				}


				var every_tick_rang = (max - min) / (splitNumber - 1)
				var splitVal = (data - min) / (max - min)
				var every_split_rang = (endAngle - startAngle) / (splitNumber - 1)
				
				var c = document.getElementById(canvasId);
				var contextCanvas = c.getContext("2d");

				// 绘制外环
				contextCanvas.save()
				contextCanvas.strokeStyle = "rgba(142,162,255, 0.2)"
				contextCanvas.lineWidth = circle_width
				contextCanvas.beginPath()
				contextCanvas.arc(circle.x, circle.y, circle.radius, startAngle * Math.PI, endAngle * Math.PI, false)
				contextCanvas.stroke()
				contextCanvas.closePath()
				contextCanvas.restore()

				// 绘制内环
				contextCanvas.save()
				contextCanvas.strokeStyle = '#3244FE'
				contextCanvas.lineWidth = circle_width
				contextCanvas.beginPath()
				contextCanvas.arc(circle.x, circle.y, circle.radius, startAngle * Math.PI, (0.8 + (1.4 * splitVal)) * Math.PI, false)
				contextCanvas.stroke()
				contextCanvas.restore()

				// 绘制刻度与刻度值
				// 绘制刻度射线
				var angleSplit = startAngle
				contextCanvas.strokeStyle = splitColor
				contextCanvas.lineWidth = splitWidth
				contextCanvas.save()
				contextCanvas.beginPath()
				for (var i = 0; i < splitNumber - 1; i ++) {
					// 刻度射线起始点
					var x0 = circle.x + (circle.radius - circle_width / 2) * Math.cos(angleSplit * Math.PI)
					var y0 = circle.y + (circle.radius - circle_width / 2) * Math.sin(angleSplit * Math.PI)
					// 刻度射线终点
					var x1 = circle.x + (circle.radius + circle_width / 2) * Math.cos(angleSplit * Math.PI)
					var y1 = circle.y + (circle.radius + circle_width / 2) * Math.sin(angleSplit * Math.PI)
					// 绘制刻度射线
					contextCanvas.moveTo(x0, y0)
					contextCanvas.lineTo(x1,y1)
					angleSplit += every_split_rang
				}
				contextCanvas.stroke()
				contextCanvas.closePath()
				contextCanvas.restore()

				// 绘制刻度文本
				var text = min
				var angleSplit_2 = startAngle
				contextCanvas.textAlign = 'center'
				contextCanvas.textBaseline = 'middle'
				contextCanvas.font = split_text_font
				contextCanvas.save()
				for (var i = 0; i < splitNumber; i ++) {
					// 刻度文本坐标点
					var xf = circle.x + (circle.radius - circle_width / 2 + offset_split_text[i]) * Math.cos(angleSplit_2 * Math.PI)
					var yf = circle.y + (circle.radius - circle_width / 2 + offset_split_text[i]) * Math.sin(angleSplit_2 * Math.PI)
					// 绘制刻度文本
					contextCanvas.fillText(text, xf, yf)
					text += every_tick_rang
					angleSplit_2 += every_split_rang
				}
				contextCanvas.stroke()
				contextCanvas.restore()

				// 绘制中间文本
				var centerText_X = circle.x
				var centerText_Y = circle.y
				contextCanvas.textAlign = 'center'
				contextCanvas.textBaseline = 'bottom'
				contextCanvas.font = center_data_font
				contextCanvas.fillStyle = 'rgba(50, 68, 254, 0.8)'
				contextCanvas.save()
				contextCanvas.fillText(data, centerText_X, centerText_Y)
				contextCanvas.fill()
				contextCanvas.restore()
			
			}
			
			initCanvasYbp1()
			
			function initCanvasYbp2 (opts = {}) {
				var canvasId = opts['id'] || 'myCanvas2'
				var data = opts['data'] || 200 // 值
				var center_data_font = '30px Arial'
				var splitNumber = opts['splitNumber'] || 41 // 刻度数量
				var max = opts['max'] || 800 // 最大值
				var min = opts['min'] || 0 // 最小值
				var circle_width = 26 // 仪表盘边宽
				var startAngle = 0.8 // 开始角度
				var endAngle = 2.2 // 结束角度
				var splitColor = opts['splitColor'] || 'rgb(255, 240, 181)' // 刻度线颜色
				var activeSplitColor = opts['activeSplitColor'] || 'rgba(254, 206, 10, 1)'
				var splitWidth = 4 // 刻度线宽度
				var offset_split_text = opts['offsetSplitText'] || [-30, -30, -30] // 刻度文本偏移
				var split_text_font = '14rpx Arial'
				var circle = { // 定义圆
          x: 200,
          y: 150,
          radius: 110
				}

				var every_tick_rang = (max - min) / 2
				var splitVal = (data - min) / (max - min)
				var every_split_rang = (endAngle - startAngle) / (splitNumber - 1)
				// 计算每一个刻度代表的数量
				var everyLineNumber = (max - min) / 41
				// 转义当前数据,符合仪表盘数据规范
				var dataCopy = data - min
				var c = document.getElementById(canvasId);
				var contextCanvas = c.getContext("2d");

				// 绘制刻度与刻度值
				// 绘制刻度射线
				var angleSplit = startAngle
				contextCanvas.lineWidth = splitWidth
				for (var i = 0; i < splitNumber; i ++) {
					if ((i * everyLineNumber) < dataCopy || (i * everyLineNumber) === dataCopy) {
						contextCanvas.strokeStyle = activeSplitColor
					} else {
						contextCanvas.strokeStyle = splitColor
					}
					contextCanvas.save()
					contextCanvas.beginPath()
					// 刻度射线起始点
					var x0 = circle.x + (circle.radius - circle_width / 2) * Math.cos(angleSplit * Math.PI)
					var y0 = circle.y + (circle.radius - circle_width / 2) * Math.sin(angleSplit * Math.PI)
					// 刻度射线终点
					var x1 = circle.x + (circle.radius + circle_width / 2) * Math.cos(angleSplit * Math.PI)
					var y1 = null
					if (i === Math.floor(splitNumber / 2)) {
						y1 = circle.y + (circle.radius + circle_width / 2 + 10) * Math.sin(angleSplit * Math.PI)
					} else {
						y1 = circle.y + (circle.radius + circle_width / 2) * Math.sin(angleSplit * Math.PI)
					}

					// 内环点
					// 刻度射线起始点
					var inx0 = circle.x + (circle.radius - circle_width / 2 - 14) * Math.cos(angleSplit * Math.PI)
					var iny0 = circle.y + (circle.radius - circle_width / 2 - 14) * Math.sin(angleSplit * Math.PI)
					// 刻度射线终点
					var inx1 = circle.x + (circle.radius + circle_width / 2 - 34) * Math.cos(angleSplit * Math.PI)
					var iny1 = circle.y + (circle.radius + circle_width / 2 - 34) * Math.sin(angleSplit * Math.PI)

					// 绘制刻度射线
					contextCanvas.moveTo(x0, y0)
					contextCanvas.lineTo(x1,y1)

					contextCanvas.moveTo(inx0, iny0)
					contextCanvas.lineTo(inx1,iny1)
					contextCanvas.stroke()
					contextCanvas.closePath()
					contextCanvas.restore()
					
					angleSplit += every_split_rang
				}

				// 绘制刻度文本
				var text = min
				var angleSplit_2 = startAngle
				contextCanvas.textAlign = 'center'
				contextCanvas.textBaseline = 'middle'
				contextCanvas.font = split_text_font
				contextCanvas.save()
				for (var i = 0; i < 3; i ++) {
					// 刻度文本坐标点
					var xf = circle.x + (circle.radius - circle_width / 2 + offset_split_text[i]) * Math.cos(angleSplit_2 * Math.PI)
					var yf = circle.y + (circle.radius - circle_width / 2 + offset_split_text[i]) * Math.sin(angleSplit_2 * Math.PI)
					// 绘制刻度文本
					contextCanvas.fillText(text, xf, yf)
					text += every_tick_rang
					angleSplit_2 += (endAngle - startAngle) / 2
				}
				contextCanvas.stroke()
				contextCanvas.restore()

				// 绘制中间文本
				var centerText_X = circle.x
				var centerText_Y = circle.y
				contextCanvas.textAlign = 'center'
				contextCanvas.textBaseline = 'bottom'
				contextCanvas.font = center_data_font
				contextCanvas.fillStyle = '#000000'
				contextCanvas.save()
				contextCanvas.fillText(data, centerText_X, centerText_Y)
				contextCanvas.fill()
				contextCanvas.restore()

			}
			
			initCanvasYbp2()
      

  </script>
</body>
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值