使用canvas绘制柱状图
使用
canvasApi来绘制一个柱状图,其效果如下。gitee源码地址、github源码地址
想要绘制上图所示的一个柱状图,我们需要将整个过程分为如下几个步骤
-
绘制坐标轴
- 绘制坐标轴
- 添加文字
- 添加刻度
-
绘制柱状图
接下来展示一如何一步一步的来绘制出如图的一个柱状图。
准备工作
在echarts使用中,有很多的配置,为了我们在绘制柱状图的过程中能够更加方便,首先创建一个和Echarts类似的一个配置项
const canvas = document.getElementById('canvas')
const context = canvas.getContext('2d')
let options = {
chartZone: [50, 50, 700, 450],//坐标轴的顶点
yAxisLable: ['0', '100', '200', '300', '400'],//y轴刻度
yMax: 400,//y轴最大值
xAxisLable: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],//x轴刻度
data: [10, 50, 200, 330, 390, 320, 220],//数据
barStyle: {//状状体的的配置
width: 70,
color: '#1abc9c'
}
}
drawBarChart(options)
function drawBarChart(options) {
context.fillStyle = '#ffffff'
context.fillRect(0, 0, canvas.width, canvas.height)
context.fillStyle = '#000000'
drawAxis(options)
drawYLable(options)
drawXLable(options)
// drawData(options)
drawDataWithGradient(options)
//如想将绘制的图形保存为jpg,可使用以下代码
// let el = document.createElement('a')
// el.href = canvas.toDataURL("image/jpeg")
// el.download = '柱状图.jpg'
// el.click()
}
绘制坐标轴
y轴绘制
function drawYLable (options) {
let lables = options.yAxisLable
let yLength = (options.chartZone[3] - options.chartZone[1]) * 0.98
let gap = yLength / (lables.length - 1)
lables.forEach(function (lable, index) {
// 填标签
let offset = context.measureText(lable).width + 20
context.strokeStyle = '#eaeaea'
context.font = '16px'
context.fillText(lable, options.chartZone[0] - offset, options.chartZone[3] - index * gap)
// 绘制小间隔
context.beginPath()
context.strokeStyle = '#353535'
context.moveTo(options.chartZone[0] - 10, options.chartZone[3] - index * gap)
context.lineTo(options.chartZone[0], options.chartZone[3] - index * gap)
context.stroke()
// 绘制横向辅助线
if(index !== 0) {
context.beginPath()
context.setLineDash([8, 8])
context.strokeStyle = '#aeaeae'
context.strokeWidth = 2
context.moveTo(options.chartZone[0], options.chartZone[3] - index * gap)
context.lineTo(options.chartZone[2], options.chartZone[3] - index * gap)
context.stroke()
context.setLineDash([])
context.strokeWidth = 4
}
})
}
坐标轴的绘制主要包括了轴的绘制和标刻两个工作,x轴的绘制类似y轴绘制。但再y轴的绘制中,加入了横向的一个辅助线的绘制,采用了虚线绘制,在绘制完成后要改回实线。
x轴绘制略。
数据绘制
function drawData(options) {
let data = options.data
let yLength = (options.chartZone[3] - options.chartZone[1]) * 0.98
let xLength = (options.chartZone[2] - options.chartZone[0]) * 0.98
let gap = xLength / options.xAxisLable.length
data.forEach(function(item, index) {
let x0 = options.chartZone[2] - (options.xAxisLable.length - index) * gap + gap / 2 - options.barStyle.width / 2
let height = item / options.yMax * yLength
let y0 = options.chartZone[3] - height
let width = options.barStyle.width
context.fillStyle = options.barStyle.color ||'#1abc9c'
context.fillRect(x0, y0, width, height)
})
}
数据的绘制就是在对应位置上绘制上一个矩形。如果想会绘制一个带渐变的矩形,可以使用createLinearGradient方法:
function drawDataWithGradient(options) {
let data = options.data
let yLength = (options.chartZone[3] - options.chartZone[1]) * 0.98
let xLength = (options.chartZone[2] - options.chartZone[0]) * 0.98
let gap = xLength / options.xAxisLable.length
let fillStyleGradient = context.createLinearGradient((options.chartZone[0]+options.chartZone[2])/2, options.chartZone[1],(options.chartZone[0]+options.chartZone[2])/2, options.chartZone[3])
fillStyleGradient.addColorStop(0, options.barStyle.color || '#1abc9c')
fillStyleGradient.addColorStop(1, 'rgba(1, 176, 241, 1)')
data.forEach(function(item, index) {
let x0 = options.chartZone[2] - (options.xAxisLable.length - index) * gap + gap / 2 - options.barStyle.width / 2
let height = item / options.yMax * yLength
let y0 = options.chartZone[3] - height
let width = options.barStyle.width
context.fillStyle = fillStyleGradient
context.fillRect(x0, y0, width, height)
})
}
总结
对于canvas绘图而言,其核心就是计算各个图形改绘制在哪里,从对矩形图的绘制可以看出,先找准坐标轴的顶点,其他都是依照坐标轴的位置来进行绘制的。所以在canvas的绘图过程中,首要便是找准参考点,其他位置则相对于参考点计算并绘制即可。