需求
有个下图所示的需求,使用highcharts有点大材小用,而且也没特别合适的,heightcharts的柱状图都比较复杂。
简单介绍两种方式实现:
- div + css3
优点:实现简单
缺点:需要多个dom元素 - canvas
优点:dom元素少
缺点:调试不方便
本文主要介绍下如何使用canvas绘制柱状图。
源码
绘制静态图形
在做一件复杂的事情时,可以将其拆分为几个小的步骤。这里我们实际要做的就是以下几件事:
- 获取canvas元素,内容上下文
let canvas = document.getElementById(id); let ctx = canvas.getContext('2d');
- 循环数组,得到每项的数据对象{name,color,percent}
- 绘制文字
- 设置字体
ctx.font = '12px Helvetica Neue,Helvetica,Arial,sans-serif';
- 绘制字体
ctx.fillStyle = '#333'; ctx.fillText(item.name, siteX, siteY);
- 设置字体
- 绘制矩形
ctx.fillStyle = item.color; ctx.fillRect(siteX, siteY + titleSpace, item.lastWidth, rectH);
- 绘制百分比
- 增加间距,设置下一次的绘图位置
动画
增加点动画体验更好。实质是在画布上绘制多次,之后清空画布,只保留最后一次的绘制结果。
思路:
- 使用requestAnimationFrame()进行重绘
- 清空画布
- 设置上一次宽度
- 匀减速
- 绘制
- 判断边界值
高倍屏下模糊处理
需要注意的是,在retina屏幕上,canvas会模糊。
原因:
实际在于屏幕的设备像素比不同,除了canvas,普通图片也会变模糊。
假设devicePixelRatio=2
,那么浏览器就会以2个像素点来渲染一个像素,相当于被拉伸了。
解决办法:
获取屏幕的设备像素比
let ratio = window.devicePixelRatio || 1;
将canvas的画布宽高*ratio,而样式宽高为一倍。即先放大再缩小。
// 设置canvas的样式宽高
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
// canvas的宽高
canvas.width = canvas.width * ratio;
canvas.height = canvas.height * ratio;
canvas的宽高区别
- 自身宽高:实际画布大小
- 样式设置的宽高:实际显示的大小
- canvas中的线条大小、文字大小等都需要乘以该倍率来进行绘制
- 涉及到宽高,位置的变量都有*ratio
- 按照一倍值绘制,使用scale()将context放大
推荐使用ctx.scale(ratio,ratio)
。因为数值较多的时候,每个都*ratio比较繁琐,容易遗漏。