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>