HTML5 快速学习二 Canvas

时间:2022-02-01 15:07:21

本篇文章开始讲解HTML5的核心功能之一:Canvas

通过Canvas可以动态生成和展示图形、图表、图像以及动画。

Canvas API功能非常多,我们将讨论最常用的功能。

我们先新建一个canvas看看。

HTML5 快速学习二 Canvas

我们给canvas加一个边框,这样比较方便看。

HTML5 快速学习二 Canvas

可以看到, canvas会创建一块矩形区域,默认情况下生成大小是300*150像素。

在页面中加入canvas后,我们便可以通过js来*地控制她。

例如 添加图片、线条以及文字,也可以在里面绘图,甚至加入高级动画。

Note

把canvas当作一个普通的标签,可以通过应用CSS的方式来改变样式,而且一些CSS属性还可以被canvas内的元素继承。

例如字体样式,在canvas内添加文字,其样式默认是同canvas元素本身是一样的。

文章提纲

  • 要点
  • 理论基础/前置条件
  • 详细步骤
  • 总结

要点

掌握使用canvas API的重要流程

掌握常用的canvas API:例如moveTo, lineTo, beginPath, closePath,stroke,fill等

充分理解例子

理论基础 -- canvas坐标

如下图,canvas中的坐标是从左上角开始,x轴沿着水平方向(按像素)向右延伸,y轴沿垂直方向向下延伸。

最左上角坐标为 (0,0) 的点为原点。

HTML5 快速学习二 Canvas

详细步骤 -- 使用HTML5 canvas API

检测浏览器支持情况

我们做两件事

  1. 我们用一段script判断浏览器支持情况。

    如果不支持可以将提示信息显示在特定的位置。

    如下图,我们用了一个id="support"的div来显示提示升级的信息。

  2. 我们在canvas中写入一段替代内容.

    如下图,如果不支持,canvas会显示替代内容。

HTML5 快速学习二 Canvas

浏览器支持

HTML5 快速学习二 Canvas

把IE调成IE7模式测试下不支持的情况:

HTML5 快速学习二 Canvas

 

利用canvas画一条对角线

对上面的例子做一些修改

HTML5 快速学习二 Canvas

在canvas中绘制一条对角线

HTML5 快速学习二 Canvas

HTML5 快速学习二 Canvas

根据上面的js代码,归纳出使用canvas API的重要流程

  1. 根据canvas ID值获取canvas对象访问权,接着定义一个context变量,调用canvas对象的getContext方法。
  2. 基于这个context执行动作(这里是画一条对角线)
  3. 通过context.stroke()完成线条的绘制。

Note

这里有一个坑。我原来将设置canvas长宽放在了style里面。如下图。

HTML5 快速学习二 Canvas

出现问题的原因:

canvas的width和height是画布的实际宽度和高度,绘制的图形在这个画布上面。

canvas的style的width和height是canvas在浏览器中被渲染的高度和宽度。

因此需要注意设置宽度时要在外面设置。

使用变换(transformation)画对角线

下面来看canvas上绘制图像的另外一种方式:使用变换(transformation)。

transformation是实现复杂canvas操作的最好方式(就单个上面绘制对角线来说看起来是更加复杂了点)

理解 变换(transformation):

把它当成是介于开发人员发出的指令和canvas显示结果之间的一个修正层 (modification layer)

注意 不管在开发中是否使用变换,修正层始终存在。

每个绘制操作的结果显示在canvas上之前都要经过修正层去修正。

虽然这么做增加了额外的复杂性,但却为绘制系统添加了更为强大的功能。

Note

不在代码中调用变换函数并不意味着可以提升canvas的性能。

canvas在执行的时候,变换会被呈现引擎隐式调用,这与开发人员是否直接调用无关。

可重用代码的一条重要建议:

一般绘制都应从原点开始,应用变换(缩放,平移,旋转等),然后不断修改代码直至达到希望的效果。

示例

HTML5 快速学习二 Canvas

这个代码的结果和上面是一模一样的。

大家注意这两种代码的差别:

对第二种方式, translate(70,140) 代表将原点移到 (70,140) 这个位置。

也就是说,接下来所有操作都是相对于 (70,140) 这个位置来操作的。

第一种情况是(70,140)à(140,70),

第二种情况是(0,0)à(70,140)à(70,-70)

第二种情况的(70, -70)是相对于新的原点(70,140)点来说的,相对于一开始的原点坐标是(70+70,-70+140),很容易看到这两种情况的结果是等价的,理解了吗?

大家体会一下。

我们归纳一下上面的操作:

  1. 根据canvas ID值获取canvas对象访问权,接着定义一个context变量,调用canvas对象的getContext方法。
  2. 保存尚未修改的context, 这样即使进行了绘制和变换操作,也可以恢复到初始状态(通过后面的restore函数)
  3. 通过translate来移动原点,这个上面已经解释过了。
  4. 基于移动过的context执行画线动作
  5. 通过context.stroke()完成线条的绘制。
  6. 最后,恢复context至原始状态,这样后续的canvas操作就不会被刚才的平移操作影响了。

画树

现在学习稍微复杂点的图形。

前面绘制的一条对角线算是一条简单路径。

实际上路径可以很复杂:多条线、曲线段、甚至是子路径。

如果想在canvas上绘制任意形状,那么你需要重点关注路径API

按照惯例,不论开始绘制何种图形,第一个需要调用的就是beginPath, 对于canvas来说,beginPath函数的最大用处是canvas需要据此来计算图形的内部和外部范围,以便完成后续的描边和填充。

路径会跟踪当前坐标,默认值是原点。

调用beginPath之后,就可以使用context的各种方法来绘制想要的形状了。

到目前为止已经使用了几个简单的context路径函数。

moveTo(x,y)

lineTo(x,y)

上面两个函数的区别是:moveTo就像是提起画笔,移动到新位置;

而lineTo告诉canvas用画笔从纸上的旧坐标画条直线到新坐标。

注意,不管调用的是哪一个,都不会真正画出图形,因为我们还没有调用stroke或者fill函数。

目前我们只是定义路径的位置,以便后面绘制时使用。

另外再介绍一个路径函数closePath, 这个函数和lineTo很像,唯一的差别是会将路径的起始坐标 自动作为 目标坐标。

clothPath还会通知canvas当前绘制的图形已经完全闭合或者形成了完全封闭的区域,这对将来的填充和描边都非常有用。

此时,可以在已有的路径中继续创建其他的子路径,或者随时调用beginPath重新绘制新路径并完全清除之前的所有路径。

1.绘制树冠

绘制树冠的函数

 

HTML5 快速学习二 Canvas

为了直观的显示图线的走势,我画了个从开始点到顶点的草图,如下

HTML5 快速学习二 Canvas

在canvas上画树的函数:

HTML5 快速学习二 Canvas

最终结果如下

HTML5 快速学习二 Canvas

下面我们对树冠做一些美化,在stroke之前添加如下代码

HTML5 快速学习二 Canvas

变成了更粗更平滑的棕色线条。

HTML5 快速学习二 Canvas

进一步美化,将闭合路径内部填充为绿色

HTML5 快速学习二 Canvas

 

HTML5 快速学习二 Canvas

注意,右边的边框也变细了。

当我们采用先描边后填充的方式,会填充一半的边框。

如果要不填充边框,需要采用先填充后描边的方式,如下。

HTML5 快速学习二 Canvas

HTML5 快速学习二 Canvas

2. 利用fillRect画树干(填充矩形区域)

我们先把translate的数值改一下,让出树干的位置。

context.translate(130,150);

通过fillRect(x, y, 宽, 高)来画出树干。

注意,这段要在context.restore();前面,否则画的位置就错了。

HTML5 快速学习二 Canvas

最终结果:

HTML5 快速学习二 Canvas

Note

fillRect(x,y,width,height)

HTML5 快速学习二 Canvas

总结

大家初步可以看到canvas的威力,可以不用借助第三方技术进行绘图。

当然目前画的东西还比较简单,下篇文章将会在这棵树的基础上加入其他元素和特殊效果,完成一幅雨水动画效果的林荫小道图。

好了,今天就到这里,欢迎大家多多评论,让下一篇文章更好:)