内容简介:Canvas API 提供了通过 JavaScript 绘制图形的能力 。它广泛用于动画、游戏图形、数据可视化、照片处理和实时视频处理领域。本文将会简单介绍下 canvas 。文章的大部分内容来源于 MDN 的这就是一个 canvas 标签,看起来和普通的 html 标签没什么不同,重要的通过 canvas 标签我们可以获取其canvas 翻译过来是画布的意思,所以接下来我们会对照画布来介绍 canvas 的API。
Canvas API 提供了通过 JavaScript 绘制图形的能力 。它广泛用于动画、游戏图形、数据可视化、照片处理和实时视频处理领域。本文将会简单介绍下 canvas 。文章的大部分内容来源于 MDN 的 canvas 教程 ,想深入了解 canvas 的可以去看一下。
初识 canvas
// 栗子 1 <canvas id="tutorial" width="150" height="150"></canvas>
这就是一个 canvas 标签,看起来和普通的 html 标签没什么不同,重要的通过 canvas 标签我们可以获取其 渲染上下文 ,canvas 的所有API都通过这个渲染上下文暴露出来,以下讲解的 API 也都基于此上下文。
canvas 翻译过来是画布的意思,所以接下来我们会对照画布来介绍 canvas 的API。
var canvas = document.getElementById('tutorial'); var ctx = canvas.getContext('2d');
绘制图形
canvas 坐标系统中,元素的左上角为坐标原点,向右下延伸坐标轴,所有图形相对于原点绘制,默认 1 网格单位对应 1 像素,比如栗子1 中的 canvas 元素就形成一个 150X150 的坐标系。 上图中的矩形坐标即为 (x, y)。
和 svg 不同,canvas 只提供了一种基本图形:矩形,不过借助路径我们可以绘制想要的任意图形。
绘制矩形
canvas 提供了三种矩形 API,我们可以通过渲染上下文获取到它们。所有 API 接受四个参数: x, y, width, height。
function draw() { var canvas = document.getElementById('canvas'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); ctx.fillRect(25, 25, 100, 100); ctx.clearRect(45, 45, 60, 60); ctx.strokeRect(50, 50, 50, 50); } }
fillRect 和 strokeRect 分别会 “填充” 和 “描边“ 一片矩形区域。调用它们会立即绘制到画布上。
clearRect 会像橡皮擦一样清除特定的矩形区域。
结果如图:
绘制路径
路径由一系列的点组成,通过路径的组合我们可以绘制需要的任何图形。绘制一条路径步骤如下:
- 通过
beginPath
创建路径,并创建一个路径缓存区,当前坐标为起点。 - 然后通过 绘制命令 绘制路径,将绘制的 直线、弧线等存入缓存区,从而组合成图形。
- 最后
closePath
会在当前坐标和起点连起一条直线(可选), 最后可以 填充 或 描边 路径。
这个绘制步骤和画画差不多,落笔、描边到填充和真实世界的心智模型是相同的。其中的重头戏就是步骤2的绘制命令:
lineTo
、 arc
、 [bezierCurveTo()](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/bezierCurveTo)
等命令分别绘制直线、弧线和贝塞尔曲线路径。而 moveTo
命令接受 x、y 两个参数,调用其会将画笔移动到指定的 x,y 坐标。
比如这里有个稍微复杂的栗子, 绘制一个吃豆人 。
路径复用
在吃豆人的栗子里,我们反复调用 roundedRect
函数来生成圆角矩形, canvas 提供了路径复用的方法,这就是 Path2D ,通过 Path2d 我们可以创建路径对象,调用绘制命令、甚至合并两个路径对象。以吃豆人中的圆角矩形函数为栗,使用Path2D 后的代码:
// A utility function to draw a rectangle with rounded corners. function roundedRect(ctx, x, y, width, height, radius) { const path = new Path2D(); path.moveTo(x, y + radius); path.lineTo(x, y + height - radius); path.arcTo(x, y + height, x + radius, y + height, radius); path.lineTo(x + width - radius, y + height); path.arcTo(x + width, y + height, x + width, y + height-radius, radius); path.lineTo(x + width, y + radius); path.arcTo(x + width, y, x + width - radius, y, radius); path.lineTo(x + radius, y); path.arcTo(x, y, x, y + radius, radius); ctx.stroke(path); }
加点样式?
canvas 通过状态机来保持 画笔 和 画布的状态,我们可以通过 API 来改变画笔的状态来绘制不同样式的图形。比如通过 fillStyle 和 strokeStyle 改变填充和描边的样式,通过 lineWidth 改变画笔的尺寸等。通过 createLinearGradient
、 [createPattern(image, type)](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/createPattern)
来绘制渐变色和图片背景,这里不再赘述。
文本绘制
坐标轴变换
加点动画?
canvas 动画的限制在于:图形绘制结束后无法再更改图形的状态(尺寸、颜色、坐标等)。这和我们熟悉的 html 元素不一样,dom 元素在渲染后还可以进行做位移、缩放等动画。由于以上原因,在 canvas 中做动画需要遵循以下步骤:
- 使用 clearRect 等方法清除画布
- 保存 canvas 的初始状态
- 绘制当前动画帧,这一步你可能会修改 canvas 状态
- 恢复 canvas 初始状态。
这里有一个 时钟动画的栗子 ,我们将不同的图形封装为对象,绘制图形时只需要调用对象的 draw
方法,这样统一了编程模型。
class Hour { constructor(ctx) { this.ctx = ctx; } draw() { this.ctx.lineWidth = 14; this.ctx.beginPath(); this.ctx.moveTo(-20, 0); this.ctx.lineTo(80, 0); this.ctx.stroke(); } }
绘制的每一帧我们会不断更新画布的状态,为了不污染下一帧的画布状态,我们需要不断调用 save
和 restore
来保存和回退画布状态。
这一章简单介绍了 canvas的基本知识,下篇文章会涉及 canvas 内的事件处理、碰撞检测等内容,并利用这些实现一些炫酷的效果,敬请期待。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 你了解HTTPS,但你可能不了解X.509
- 你真的了解Mybatis的${}和#{}吗?是否了解应用场景?
- 你所了解的 array_diff_uassoc 真的是你了解的那样吗?
- 图文了解 Kubernetes
- 深入了解 JSONP
- 一文了解 Kubernetes
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
RGB转16进制工具
RGB HEX 互转工具
Markdown 在线编辑器
Markdown 在线编辑器