前言
最近也是在学习 canvas,跟着绘制了一个最基本柱状图,canvas 是一个基于 HTML5 的绘图标准,提供了一系列的 API 可以用来绘制图形,包括直线、矩形、圆形、文本等等。我介绍如何使用 canvas 绘制简单的柱状图,并优化技巧,使得代码更加高效
绘制柱状图
在上图的柱状图里有什么?
绘制坐标轴
首先来对画布进行一个初始化,获取 canvas 元素并获取其 2D 上下文对象的,对 canvas 元素的尺寸进行缩放,将 canvas 元素的 CSS 宽高设置为它在 HTML 中设置的宽度和高度,确保 canvas 在页面中显示的大小不会改变,然后根据设备像素比扩大画布的像素,提高图像的清晰度,防止模糊发虚
<canvas id="canvas" width="600" height="500"></canvas>
<script>
const canvas = document.getElementById("canvas");
const ctx = canvas.getContext("2d");
canvas.style.width = canvas.width + "px";
canvas.style.height = canvas.height + "px";
canvas.width = canvas.width * 1.5;
canvas.height = canvas.height * 1.5;
</script>
复制代码
然后定义一些相关的属性,在绘制的过程中以备使用
const ht = canvas.clientHeight; //画布高度
const wd = canvas.clientWidth; //画布宽度
const pad = 20; //边距
const bottomPad = 20; //底部边距
const step = 100; //坐标轴刻度间距
复制代码
首先要把坐标轴的那条直角画出来,设置 lineWidth 线宽为 2,strokeStyle 笔画颜色为'lightblue',绘制的起点为定义好的常量 pad 为 20,一直绘制到最底部然后再往右边绘制
// 绘制坐标轴
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = "lightblue";
ctx.moveTo(pad, pad);
ctx.lineTo(pad, ht * 1.5 - bottomPad);
ctx.lineTo(wd * 1.5 - pad, ht * 1.5 - bottomPad);
ctx.stroke();
ctx.closePath();
复制代码
然后循环绘制 x 轴方向刻度,起点 x 轴固定不变为 pad,y 轴坐标为画布高度 * 1.5 - bottomPad - i * 坐标轴刻度间距,终点 x 轴为 pad + 10,y 轴和起点 y 轴一致
循环 y 轴方向刻度也是同理,只不过是反过来了
// 绘制x轴方向刻度
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "#666";
for (let i = 1; i < Math.floor((ht * 1.5) / step); i++) {
ctx.moveTo(pad, ht * 1.5 - bottomPad - i * step);
ctx.lineTo(pad + 10, ht * 1.5 - bottomPad - i * step);
}
ctx.stroke();
ctx.closePath();
// 绘制y轴方向刻度
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = "#666";
for (let i = 1; i < Math.floor((wd * 1.5) / step); i++) {
ctx.moveTo(pad + i * step, ht * 1.5 - bottomPad);
ctx.lineTo(pad + i * step, ht * 1.5 - bottomPad + 10);
}
ctx.stroke();
ctx.closePath();
复制代码
绘制柱子
柱子实际上就是一个矩形,绘制矩形分三种,有描边有填充,无描边有填充,有描边无填充
有描边有填充通过rect
方法绘制出一个矩形的路径,但不会实际绘制矩形,还需要通过stroke
方法和fill
方法来绘制描边和填充
无描边有填充通过fillRect
方法绘制一个填充的矩形,有描边无填充通过strokeRect
方法绘制一个边框矩形
无论是rect
方法,fillRect
方法还是strokeRect
方法都要传入四个参数:x 轴坐标,y 轴坐标,宽度,高度
// 绘制矩形填充
ctx.beginPath();
ctx.lineWidth = 5; //线条宽度
ctx.strokeStyle = "orange"; //笔画颜色
ctx.fillStyle = "hotpink"; //填充颜色
ctx.rect(100, 100, 300, 200); //绘制矩形路径
ctx.stroke(); //绘制描边
ctx.fill(); //填充
ctx.closePath();
ctx.beginPath();
ctx.lineWidth = 4;
ctx.strokeStyle = "blue";
ctx.strokeRect(100, 310, 300, 200); //绘制矩形(无填充)
ctx.closePath();
ctx.beginPath();
ctx.fillStyle = "skyblue";
ctx.fillRect(410, 310, 300, 200); //绘制矩形(填充)
ctx.closePath();
复制代码
知道如何绘制矩形然后就可以绘制出柱子了,只需要绘制有填充五描边的矩形就行了,于是循环调用fillRect
方法绘制
ctx.beginPath();
for (let i = 1; i < Math.floor((wd * 1.5) / step); i++) {
const height = Math.random() * 500 + 50;
ctx.fillStyle = "#5470C6";
ctx.fillRect(i * step, ht * 1.5 - bottomPad, 40, -height);
}
ctx.closePath();
复制代码
评论