canvas仪表盘

1,021 阅读2分钟

demo地址

源码地址

预览效果

需求

  1. 背景是2层渐变叠加的效果
  2. 适配不同手机屏幕的宽度,高度是宽度的2/3
  3. 仪表盘不是半圆,左右多出2个刻度
  4. 动画效果,刻度变化,数字变化

拿到这个需求的时候,第一反应是第三方库,调研之后,echarts最接近的例子,需求还是比较自定义化,echarts不太满足,只能造(怕)轮(被)子(喷)了。

背景是2层渐变叠加的效果

canvas支持渐变,和css设置挺像

 // 创建线性渐变
var grd = ctx.createLinearGradient(0, 0, 200, 0);
grd.addColorStop(0, "blue"); // 第二个参数支持rgba
grd.addColorStop(1, "red"); 
// 填充渐变
ctx.fillStyle = grd;
ctx.fillRect(10, 10, 150, 80);

考虑到是2层渐变叠加,canvas内部是挤压的(防止图片模糊,canvas进行缩放绘制)

渐变都是放在style上面设置,会导致下载的图片没有渐变效果

<div class="gauge-wrap">
	<canvas id="gauge" class="gauge" width="750" height="500"></canvas>
</div>
.gauge-wrap-high{
  background: -webkit-linear-gradient(135deg, rgba(255,255,255,0.00) 0%, rgba(255,255,255,0.19) 26%, rgba(255,255,255,0.25) 28%, rgba(255,255,255,0.00) 100%);
}
.gauge-high{
  background: -webkit-linear-gradient(90deg, #414141 3%, #030303 100%);
}

适配不同手机屏幕的宽度,高度是宽度的2 / 3 ≈ 0.66

canvas外面div的样式

.gauge-wrap{
  height: 66vw;
}

canvas画布大小

const width = 750
const height = width * 2 / 3

仪表盘不是半圆,左右多出2个刻度

从视觉图中数刻度数量,如果正好排好一个圆总共80个刻度

每个刻度的弧度const deg = Math.PI / 40

ctx.rotate(deg)deg是正数时旋转顺时针方向deg弧度,所以默认顺时针旋转38个刻度的弧度

动画效果,刻度变化,数字变化

使用window.requestAnimationFrame进行递归循环,刻度从初始位置按照固定速度递增,数字从0递增

每次重新绘制前需要清空画布ctx.clearRect(0, 0, width, height)

总结

canvas适合于2d的绘制,一旦涉及3d,需要webgl的canvas。