第18章 HTML5动画设计

Canvas是HTML5新增的开发跨平台动画和游戏的标准解决方案,它具备对图像和视频进行像素级操作的能力,这为Web图形和视频处理打开了广阔的空间。借助HTML5 canvas技术,可以在Web中绘制各种图形。虽然在此之前也有基于XML的绘图技术,如VML、SVG等。而Canvas是基于像素的绘图,它相当于画板的html节点,开发者通过JavaScript脚本可以轻松实现任意绘图。

canvas是HTML5新增的专门用来绘制图形的元素。在页面上放置一个canvas元素,就相当于在页面上放置了一块画布,可以在其中进行图形的描绘。在canvas元素里进行绘画,不需要鼠标作画。事实上,canvas元素只是一块无色透明的区域,需要利用JavaScript编写在其中进行绘画的脚本。从这个角度来说,读者可以把它理解为类似于其他开发语言中的canvas画布。本章将详细介绍Canvas渲染上下文、坐标系统、画布状态、变形合成,以及高级的图像和视频处理技巧和应用案例。

【学习重点】

▲ 了解HTML 5 canvas概述

▲ 使用JavaScript绘制基本图形

▲ 在网页中绘制曲线

▲ 能够使用JavaScript变换图形、组合和裁切图形

▲ 定义图形颜色和样式

▲ 绘制文字和嵌入图像

18.1 HTML5 canvas概述

HTML5 canvas元素及随其而来的编程接口Canvas API应用前景极为广阔。简单地说,canvas元素能够在网页中创建一块矩形区域,这块矩形区域可以称为画布,这其中可以绘制各种图形。可别小看了这个画布,它能实现无限的可能性。接下来从最简单的部分开始,逐步认识Canvas的强大功能。

18.1.1 在页面中添加canvas元素

如果要向页面中添加canvas元素,可以使用下面的代码。默认情况下,Canvas所创建的矩形区域大小为宽300像素、高150像素,可以使用width与height属性来自定义其宽度和高度。

     <!DOCTYPE HTML><html><body><canvas id="myCanvas" width="200" height="100"></canvas></body></html>

以上代码只是简单地创建了一个Canvas对象,在浏览器打开的页面上什么都不会看到。但如果是在Dreamweaver的设计视图中,可以看到这个矩形区域,如图18.1所示。

可以在canvas元素中使用标准的CSS边框属性来设置边框的外观。例如,使用下面示例中的style属性,可以为canvas元素添加一个实心的边框。

     <!DOCTYPE HTML><html><body><canvas id="myCanvas" style="border:1px solid;" width="200" height="100"></canvas></body></html>

以上代码在Chrome浏览器中的运行结果如图18-2所示。

图18-1 Dreamweaver的设计视图中看到的矩形区域

图18-2 为canvas元素添加实心边框

观察以上代码,注意其中的id="myCanvas",在接下来的小节中将介绍JavaScript如何使用id来找到canvas元素。

18.1.2 Canvas如何绘制图形

canvas元素本身并不能实现图形绘制功能,绘制图形的工作需要由JavaScript来完成。使用JavaScript,可以在canvas元素内部添加线条、图片、文字,也可以在其中绘画,并且还能够加入高级动画。

【操作步骤】

第1步,在HTML5页面中添加canvas元素,必须定义canvas元素的id属性值以便接下来调用。

     <canvas id="myCanvas" width="200" height="100"></canvas>

第2步,使用id寻找canvas元素。在JavaScript代码中使用document.getElementById等方法,利用先前在canvas元素中指定的id来寻找Canvas。

     var c=document.getElementById("myCanvas");

第3步,通过canvas元素的getContext()方法来获取其上下文(Context),即创建Context对象,以获取允许进行绘制的2D环境。

     var context=c.getContext("2d");

这里的getContext("2d")是用于返回一个内建的HTML5对象(CanvasRenderingContext2D对象),使用该对象可用于在canvas元素中绘制图形,目前强制必须支持的只有"2d",即二维绘图。getContext("2d")对象能够实现一个画布所使用的大多数方法,例如绘制路径、矩形、圆形、字符和添加图像(如下面将要介绍到的fillStyle、fillRect等)。如果将来canvas元素支持3D,则getContext()方法可能会允许使用"3d"这个字符串参数。

第4步,使用JavaScript进行绘制。例如使用以下代码可以绘制一个位于画布中央的矩形。

     context.fillStyle="#FF00FF";context.fillRect(50,25,100,50);

这两行代码中,fillStyle将要绘制的矩形的填充颜色定义为粉红色,而fillRect则指定了要绘制的矩形的位置和尺寸。图形的位置由前面的Canvas坐标值决定,尺寸由后面的宽度和高度值决定。在本例中,坐标值为(50,25),尺寸为宽100像素、高50像素,根据这些数值,粉红色矩形将出现在画面的中央。

【示例】下面给出完整的示例代码。

     <!DOCTYPE HTML><html><body><canvas id="myCanvas" style="border:1px solid;" width="200" height="100"></canvas><script type="text/JavaScript">var c=document.getElementById("myCanvas");var context=c.getContext("2d");context.fillStyle="#FF00FF";context.fillRect(50,25,100,50);</script></body></html>

以上代码在Chrome浏览器中的运行结果如图18-3所示。在画布周围加了边框是为了能更清楚地看到中间矩形位于画布的什么位置。

图18-3 Canvas如何绘制图形

18.1.3 认识Canvas坐标

在18.1.2节的示例中,提到了坐标。在Canvas中绘制图形时,需要为图形指定具体位置,fillRect(50,25,100,50)中的前两个参数便是用于指定位置的x轴和y轴的坐标值。在Canvas中,坐标原点(0,0)位于Canvas的左上角,x轴水平向右延伸,y轴垂直向下延伸,如图18-4所示。

图18-4 认识Canvas坐标

18.1.4 何时不用Canvas

canvas元素尽管可以实现非常强大且复杂的功能,但如果HTML页面中有比canvas元素更合适的元素存在,则不必再用canvas。例如,用canvas元素来渲染HTML页面的标题样式标签(如h1、h2等)便不太合适。

18.1.5 如果浏览器不支持Canvas

有些浏览器可能不支持canvas元素,因此就需要为这些浏览器提供替代显示的内容。方法比较简单,只需要直接在canvas元素内插入替代内容即可。不支持canvas的浏览器会忽略canvas元素而直接显示替代内容,支持Canvas的浏览器则会正常地渲染Canvas。

【示例】把一行说明文字或者一幅替代图片插入canvas元素内,以作为替代显示的内容。

     <!DOCTYPE HTML><html><body><canvas id="myCanvas" style="border:1px solid;" width="200" height="100">您的浏览器不支持canvas元素,请更新或更换您的浏览器。</canvas></body></html>

以上代码在IE 6浏览器中的运行结果如图18-5所示。因其不支持canvas元素,所以显示了canvas元素中插入的替代文本。

图18-5 显示canvas元素中插入的替代文本

18.1.6 检测浏览器支持

除了用上述方法在不支持canvas的浏览器中显示替代文本之外,还可以使用JavaScript脚本来检测浏览器是否支持canvas,方法是判断getContext()函数是否存在。

【示例】以下代码在IE 6浏览器中的运行结果如图18-6所示,因其不支持canvas元素,所以显示“您的浏览器不支持Canvas!”。而在Chrome浏览器中的运行结果如图18-7所示,显示的是“您的浏览器支持Canvas!”。当然也可以用document.write方法在网页中显示类似的信息。

图18-6 显示“您的浏览器不支持Canvas!”

图18-7 显示“您的浏览器支持Canvas!”

18.2 绘制基本图形

“万丈高楼平地起”,任何事物都是从最简单最基础的部分开始筑建,但最终却会形成或复杂或庞大的结构。HTML5的canvas能够实现最简单直接的绘图,也能通过编写脚本实现极为复杂的应用,如各种美妙绝伦的图形、精彩纷呈的游戏等。本节首先介绍如何使用Canvas和JavaScript实现最简单的图形绘制,包括绘制直线、矩形和圆形,一起来初窥Canvas中绘图的基本原理和方法。

18.2.1 绘制直线

绘制直线可以使用下面示例中的JavaScript代码。其中调用了3个方法:moveTo()、lineTo()和stroke()。

【示例】以下代码在Chrome浏览器中的运行结果如图18-8所示,绘制了一条贯穿画布的对角线。

     <!DOCTYPE HTML><html><body><canvas id="myCanvas" style="border:1px solid;" width="200" height="100"></canvas><script type="text/JavaScript">var c=document.getElementById("myCanvas");var context=c.getContext("2d");context.moveTo(0,0);context.lineTo(200,100);context.stroke();</script></body></html>

moveTo()方法用于建立新的子路径,并规定其起始点为(x,y),用法如下:

     context.moveTo(x,y)

lineTo()方法用于从moveTo()方法规定的起始点开始绘制一条到规定坐标的直线,如果前面没有用moveTo()方法规定子路径的起始点,则lineTo()方法等同于moveTo()方法。例如在上面的示例中,lineTo()方法绘制了一条从(0,0)到(200,100)的直线。lineTo()方法的用法如下:

     context.lineTo(x,y)

上面的两个方法规定了直线路径的起点和终点,而stroke()方法用于沿该路径绘制一条直线。

18.2.2 绘制矩形

绘制矩形可以使用下面示例中的JavaScript代码。

【示例1】以下代码在Chrome浏览器中的运行结果如图18-9所示,绘制了一个大小为200×100的粉红色矩形,且左上角坐标为(0,0)。

     <!DOCTYPE HTML><html><body><canvas id="myCanvas" style="border:1px solid;" width="300" height="150"></canvas><script type="text/JavaScript">var c=document.getElementById("myCanvas");var context=c.getContext("2d");context.fillStyle="#FF00FF";context.fillRect(0,0,200,100);</script></body></html>

图18-8 绘制直线

图18-9 绘制矩形

在上面的示例代码中,fillStyle属性用于指定要绘制的图形的填充颜色,而fillRect()方法用于以指定的颜色填充一个矩形,括号中的参数用于指定矩形的坐标位置与大小。

除了可以使用fillStyle和fillRect,还可以使用strokeStyle和strokeRect。fill是填充,而stroke是轮廓,所以用strokeStyle和strokeRect绘制的是矩形轮廓。例如,在以上代码中添加下面的代码可以在粉红色矩形上再绘制一个白色的矩形轮廓。

     context.strokeStyle="#FFFFFF";context.strokeRect(0,0,100,50);

以上代码在Chrome浏览器中的运行结果如图18-10所示,在粉红色矩形上方绘制了一个大小为100×50的白色矩形轮廓,且左上角坐标为(0,0)。

图18-10 绘制矩形

在使用fillStyle或strokeStyle指定颜色值时,颜色值使用的是符合CSS3标准的字符串。

【示例2】下面这些例子中fillStyle表示的是同一种颜色。

     context.fillStyle="#FF0000";context.fillRect(0,0,10,10);context.fillStyle="red";context.fillRect(20,20,10,10);context.fillStyle="rgb(255,0,0)";context.fillRect(40,40,10,10);context.fillStyle="rgb(100%,0%,0%)";context.fillRect(60,60,10,10);context.fillStyle="rgba(255,0,0,1)";context.fillRect(80,80,10,10);

综上所述,可以看到绘制矩形有两种方法,即fillRect和strokeRect,前者用于绘制用颜色填充区域的矩形,后者用于绘制轮廓(或线条)。而为图形指定颜色用到了两个属性,即fillStyle和strokeStyle,前者用于指定要绘制的填充区域的颜色,后者用于指定要绘制的轮廓(或线条)的颜色。

18.2.3 绘制圆形

本节介绍如何绘制圆形。在绘制圆形时,用到beginPath()、arc()、closePath()、fill()和stroke()这5个方法。

【示例1】下面以示例进行说明,代码如下:

     <!DOCTYPE HTML><html><body><canvas id="myCanvas" style="border:1px solid;" width="300" height="150"></canvas><script type="text/JavaScript">var c=document.getElementById("myCanvas");var context=c.getContext("2d");context.fillStyle="#FF00FF";context.beginPath();context.arc(100,75,50,0,Math.PI*2,true);context.closePath();context.fill();</script></body></html>

以上代码在Chrome浏览器中的运行结果如图18-11所示,在300×150大小的画布上绘制了一个半径为50的圆形。

图18-11 绘制圆形

圆形的绘制仍是采用绘制路径并填充颜色的方法。beginPath()方法用于开始绘制路径,closePath()方法用于结束绘制路径。调用beginPath()方法后,在Canvas中进行一系列图形的绘制,绘制完成后,应该使用closePath()方法将图形闭合起来。在这两个语句中间的arc()方法用于绘制圆形,其用法如下:

     context.arc(x, y,radius,startAngle, endAngle,anticlockwise);

arc()方法本意为用于绘制弧线,当采用适当的参数后,即可绘制圆形。参数中的x,y为起点坐标,radius为圆形的半径,startAngle为开始的角度,endAngle为结束的角度,anticlockwise为是否按逆时针方向进行绘制。

【示例2】为了更好地理解这些方法,再看下面的示例:

以上代码在Chrome浏览器中的运行结果如图18-12所示。在上面的示例中,要用到stroke()方法,该方法用于在显示设备中输出线条,而示例1中用fill()方法输出的是填充颜色。这里没有用closePath()方法,因为该方法会在路径不闭合时,补上一条线将路径闭合起来。例如,如果在以上示例中的“context.stroke();”语句前添加“context.closePath();”语句,则会得到如图18-13所示的输出结果。

图18-12 绘制弧线

图18-13 封闭路径

18.2.4 绘制三角形

综合运用上述的一些方法和属性,使用绘制路径的方法可以自由绘制其他形状,如三角形。

【示例1】请看下面的示例。

     <!DOCTYPE HTML><html><body><canvas id="myCanvas" style="border:1px solid;" width="200" height="200"></canvas><script type="text/JavaScript">var c=document.getElementById("myCanvas");var context=c.getContext("2d");context.fillStyle="red";context.beginPath();context.moveTo(25,25);context.lineTo(150,25);context.lineTo(25,150);context.fill();</script></body></html>

以上代码在Chrome浏览器中的运行结果如图18-14所示。

图18-14 绘制实心三角形

【示例2】而如果要绘制空心三角形,即只有轮廓的三角形,则要改用strokeStyle属性和stroke()方法,请看下面的示例。

     <!DOCTYPE HTML><html><body><canvas id="myCanvas" style="border:1px solid;" width="200" height="200"></canvas><script type="text/JavaScript">var c=document.getElementById("myCanvas");var context=c.getContext("2d");context.strokeStyle="red";context.beginPath();context.moveTo(25,25);context.lineTo(150,25);context.lineTo(25,150);context.closePath();context.stroke();</script></body></html>

以上代码在Chrome浏览器中的运行结果如图18-15所示。

图18-15 绘制空心三角形

18.2.5 清空画布

在Canvas中绘制了一些图形后,许多时候可能需要清除这些图形,例如一些绘图程序中的橡皮工具可能会用到这一功能。使用clearRect()方法用于清除指定的矩形区域内的所有绘制图形,显示出画布的背景,该方法用法如下:

     context.clearRect(x,y,width,height);

【示例】通过本示例来体验如何清空画布。

以上代码在Chrome浏览器中的运行结果如图18-16所示,先是在画布上绘制一段弧线。如果单击“清空画布”按钮,则会清除这段弧线,如图18-17所示。

图18-16 绘制弧线

图18-17 清空画布

18.3 绘制曲线

相对于绘制直线、矩形、圆形等简单图形而言,绘制曲线是比较富有挑战性的,但是一旦洞悉其原理,就能够创建出许多复杂的图形。贝塞尔曲线在电脑图形学中的作用至关重要,其应用也非常的广泛,例如在一些数学软件、矢量绘图软件和三维动画软件中,经常会见到贝塞尔曲线,主要用于数值分析领域或产品设计和动画制作领域。本节介绍如何在Canvas中绘制贝塞尔曲线,包括二次方曲线和三次方曲线。有关贝塞尔曲线的知识可以参考相关书籍或维基百科中的条目“贝塞尔曲线”。

18.3.1 绘制二次方贝塞尔曲线

quadraticCurveTo()方法用于绘制二次方贝塞尔曲线,其用法如下:

     context.quadraticCurveTo(cp1x, cp1y, x, y);

其中参数cp1x和cp1y是控制点的坐标,x和y是终点坐标。

【示例】本示例不但绘制了一条二次方贝塞尔曲线,还绘制出了其控制点和控制线。

以上代码在Chrome浏览器中的运行结果如图18-18所示,其中曲线即为二次方贝塞尔曲线,两条直线为控制线,两直线的交点即曲线的控制点。

图18-18 二次方贝塞尔曲线及其控制点

18.3.2 绘制三次方贝塞尔曲线

bezierCurveTo()方法用于绘制三次方贝塞尔曲线,其用法如下:

     context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y, x, y);

其中参数cp1x和cp1y是第一个控制点的坐标,cp2x和cp2y是第二个控制点的坐标,x和y是终点坐标。

【示例】本示例不但绘制了一条三次方贝塞尔曲线,还绘制出了两个控制点和两条控制线。

以上代码在Chrome浏览器中的运行结果如图18-19所示,其中曲线即为三次方贝塞尔曲线,两条直线为控制线,两直线上方的端点即为曲线的控制点。

图18-19 三次方贝塞尔曲线

18.4 变换图形

适当地运用图形的变换(Transformations,如旋转和缩放图形等),可以创建出大量复杂多变的图形。在了解图形的变换之前,应该首先了解一下Canvas状态的保存与恢复。

18.4.1 保存与恢复Canvas状态

Canvas状态指的是当前画面所有样式、变形和裁切的一个快照,以堆(Stack)的方式保存。Save()和restore()方法用于保存和恢复Canvas状态,这两个方法都不需要任何参数,用法如下:

     context.save();context.restore();

save()方法可以暂时将当前的状态保存到堆中,这些状态可以是各种属性(如strokeStyle、fillStyle、globalCompositeOperation等)的值、当前应用的变形、当前裁切的路径等。restore()方法用于将上一个保存的状态从堆中再次取出,恢复该状态的所有设置。

【示例】在本示例中,首先绘制一个矩形,填充颜色为#ff00ff,轮廓颜色为蓝色,然后保存这个状态,再绘制另外一个矩形,填充颜色为#ff0000,轮廓颜色为绿色,最后恢复第一个矩形的状态,并绘制两个小的矩形,则其中一个矩形填充颜色必为#ff00ff,另外矩形轮廓颜色必为蓝色,因为此时已经恢复了原来保存的状态,所以会沿用最先设定的属性值。

以上代码在Chrome浏览器中的运行结果如图18-20所示,可以尝试将context.restore();一行删除,然后再查看代码的运行结果,比较一下有何不同。

图18-20 保存与恢复Canvas状态

18.4.2 移动坐标空间

前面讲过,画布的坐标空间默认以画布左上角(0,0)为原点,然后x轴水平向右为正向,y轴垂直向下为正向,该坐标空间的单位通常为像素。在绘制图形时,可以使用translate()方法为移动坐标空间,使画布的变换矩阵发生水平和垂直方向的偏移,其用法如下:

     context.translate(dx, dy);

其中dx和dy分别为坐标原点沿水平和垂直两个方向的偏移量,如图18-21所示。

图18-21 坐标空间的偏移示意图

在进行图形变换之前,最好养成先使用save()方法保存当前状态的好习惯。在许多情况下,使用restore()方法来自动恢复原来的状态要比手动恢复更加高效,特别当重复某种运算时。

【示例】在本示例中,综合运用了save()、restore()、translate()方法来绘制一个伞状图形。仔细阅读代码并体会一些关键语句的用途,有助于更好地理解。

以上代码在Chrome浏览器中的运行结果如图18-22所示。可见,Canvas中图形移动的实现,其实是通过改变画布的坐标原点来实现的,所谓的“移动图形”,只是“看上去”的样子,实际移动的是坐标空间。领会并掌握这种方法,对于随心所欲地绘制图形非常有帮助。

18.4.3 旋转坐标空间

rotate()方法用于以原点为中心旋转Canvas,实质仍是旋转Canvas上下文对象的坐标空间,其用法如下:

     context.rotate(angle);

rotate()方法只有一个参数,即旋转角度angle,旋转角度以顺时针方向为正方向,以弧度为单位,旋转中心为Canvas的原点,如图18-23所示。

图18-22 移动坐标空间

图18-23 以原点为中心旋转Canvas

【示例】以下Chrome浏览器中的运行结果如图18-24所示。在本例中,每次开始绘制图形之前,先将坐标空间旋转PI*(2/4+i/4),再将坐标空间沿y轴负方向移动100,然后开始绘制图形,从而实现使图形沿一中心点平均旋转分布。

图18-24 旋转坐标空间

18.4.4 缩放图形

scale()方法用于增减Canvas上下文对象中的像素数目,从而实现图形或位图的放大或缩小,其用法如下:

     context.scale(x,y);

其中x、y为必须接收的参数,x为横轴的缩放因子,y为纵轴的缩放因子,它们的值必须是正值。如果需要放大图形,则将参数值设置为大于1的数值;如果需要缩小图形,则将参数值设置为小于1的数值,当参数值等于1时则没有任何效果。

【示例】以下代码在Chrome浏览器中的运行结果如图18-25所示。在本例中,使用scale(0.95,0.95)来缩小图形到上次的0.95,共循环80次,同时移动和旋转坐标空间,从而实现图形呈螺旋状由大到小的变化。

图18-25 缩放图形

18.4.5 矩阵变换

transform()方法用于直接对变形矩阵做修改,即进行矩阵变换。矩阵变换常用于坐标变换不能达到预期效果的情况,能够实现比普通的坐标变换更为复杂的变形。

变换矩阵是数学线性代数中的一个概念,在计算机图形学中,这个矩阵能够实现二维图形的变形。Canvas的上下文对象事实上便是创建了一个变换矩阵,在这个上下文对象中,一个元素经过渲染后可以得到一张位图,通过对这个矩阵进行变换,即对这个位图上每一点进行变换,从而使图形产生诸如平移、缩放、旋转、切变以及镜像反射等效果。transform()方法的用法如下:

     context.transform(m11, m12, m21, m22, dx, dy);

该方法必须将当前的变换矩阵与下面的矩阵进行乘法运算。

     m11  m21  dxm12  m22  dy0    0    1

其中要注意m11、m12、m21、m22、dx、dy这几个参数,它们是竖着排列的。通过下面的基本公式,可以了解到矩阵变换是如何计算的。具体的原理要参考有关矩阵乘法的知识,在此不作赘述。

其中x、y为初始坐标,x'和y'是矩阵变换之后得到的新的坐标。也就是说,所谓的矩阵变换即使用变换矩阵对初始坐标进行变换,从而得到新的坐标,并进而实现平移、缩放、旋转、切变以及镜像反射等效果。如果按照矩阵乘法的运算法则,可以将上述基本公式作以简化,即:

x'=(m11)x+(m21)y+dx

y'=(m12)x+(m22)y+dy

再回过头来看前面讲过的移动(translate)、缩放(scale)和旋转(rotate)坐标空间,这3种方法其实都是矩阵变换的特例而已。下面使用矩阵变换来分别解释一下这3种方法。

1.移动(translate)

translate(x,y)可以用下面的transform()方法来代替:

     context.transform(0,1,1,0,dx,dy);

     context.transform(1,0,0,1,dx,dy);

如果将这些参数值代入简化的基本公式,则以上的形式都可以这样来表示:

x'=x+dx

y'=y+dy

其中dx为原点沿x轴移动的数值,dy为原点沿y轴移动的数值。

2.缩放(scale)

scale(x,y)可以用下面的transform()方法来代替:

     context.transform(m11,0,0,m22,0,0);

     context.transform(0,m12,m21,0,0,0);

如果将这些参数值代入简化的基本公式,则以上的形式都可以这样来表示:

x'=(m11)x

y'=(m22)y

x'=(m12)x

y'=(m21)y

此处dx、dy都为0表示坐标原点不变。m11、m22或m12、m21为沿x、y轴放大的倍数。

3.旋转(rotate)

rotate(angle)比较复杂一些,需要用到三角函数的知识,可以用下面的transform()方法来代替:

     context.transform(cosθ,sinθ,-sinθ, cosθ,0,0);

其中的θ为旋转角度的弧度值,dx、dy都为0表示坐标原点不变。

如果将这些参数值代入简化的基本公式,则以上的形式都可以这样来表示:

x'=x* cosθ-y* sinθ

y'=x* sinθ+ y* cosθ

下面根据以上分析来替换前面介绍过的“缩放图形”示例的代码,那么应该可以用下面的:

     ctx.transform(0.95,0,0,0.95,30,30);

来代替:

     ctx.translate(30,30);ctx.scale(0.95,0.95);

读者可以自行验证一下。但是先不要期望用一个transform()方法来代替以下3条语句,因为transform()方法非常复杂,如果有时间可以多参考一些矩阵变换的文章或书籍,以及计算机图形学的知识,然后再深入研究和实践如何实现更高级的应用。

     ctx.translate(30,30);ctx.scale(0.95,0.95);ctx.rotate(Math.PI/12);

setTransform()方法用于将当前的变换矩阵进行重置为最初的矩阵,然后以相同的参数调用transform()方法,即先set(重置)再transform(变换),用法如下:

     context.setTransform(m11, m12, m21, m22, dx, dy);

【示例】在该示例中,使用setTransform()方法将前面已经发生变换的矩阵首先重置为最初的矩阵,即恢复最初的原点,然后再将坐标原点改为(10,10),并以新的坐标为基准绘制一个蓝色的矩形。

以上代码在Chrome浏览器中的运行结果如图18-26所示。在本例中,使用scale(0.95,0.95)来缩小图形到上次的0.95,共循环80次,同时移动和旋转坐标空间,从而实现图形呈螺旋状由大到小的变化。

图18-26 矩阵重置并变换

18.5 组合和裁切图形

当在Canvas中绘制多个图形时,可以指定图形的组合(Compositing)方式,使其呈现出不同的效果。本节通过实例介绍在Canvas中进行图形组合与裁切的方法与技巧。

18.5.1 组合图形

当两个或两个以上的图形存在重叠区域时,默认情况下一个图形画在前一个图形之上。通过指定图形globalCompositeOperation属性的值可以改变图形的绘制顺序或绘制方式,从而实现更多种可能。此外,还可以使用globalAlpha属性来指定图形的透明度。

【示例】在本示例中,设置所有图形的透明度为1,即不透明,可以在0~1之间取值从而改变图形的透明度。globalCompositeOperation属性的值指定为source-over,即默认设置,新的图形会覆盖在原有图形之上,也可以指定其他值,详见表18-1。

以上代码在Chrome浏览器中的运行结果如图18-27所示。如果将globalAlpha的值更改为0.5 (context.globalAlpha=0.5;),则两个图形都会呈现为半透明,如图18-28所示。

图18-27 图形的组合

图18-28 半透明效果

表18-1给出了globalCompositeOperation属性所有可用的值。灵活使用这些属性值,必能创造出丰富多彩的图形。表中的图例矩形表示为B,为先绘制的图形(原有内容为destintation),圆形表示为A,为后绘制的图形(新图形为source)。在应用时注意globalCompositeOperation语句的位置,应处在原有内容与新图形之间。Chrome浏览器支持大多数属性值,无效的在表18-1中已经标出。Opera对这些属性值的支持相对来说更好一些。

表18-1 globalCompositeOperation属性所有可用的值

续表

18.5.2 裁切路径

clip()方法用于裁切路径,其原理与绘制普通Canvas图形类似,只不过clip的作用是形成一个蒙版,没有被蒙版的区域会被隐藏。

【示例】如果绘制一个圆形,并进行裁切,则圆形之外的区域将不会绘制在Canvas上。

以上代码在Chrome浏览器中的运行结果如图18-29所示。可以看到,只有圆形区域内的螺旋图形被显示出来,其余部分被“遮”住了。

图18-29 图形的组合

18.6 定义颜色和样式

在前面已经介绍过可以为图形设置填充颜色与轮廓颜色,使用的是fillStyle()和strokeStyle()方法。Canvas支持更多的颜色和样式选项,具体还包括线型、渐变、图案、透明度和阴影。巧妙地运用这些可选项,对于绘制出引人注目的内容非常有帮助。

18.6.1 应用线型

通过设置下面的4个属性值,可以为线条应用不同的线型,分别为线条的粗细、端点样式、两线段连接处样式、绘制交点的方式。

     lineWidth=valuelineCap=typelineJoin=typemiterLimit=value

下面分别通过实例详细介绍这些属性。

1.lineWidth(设置线条的粗细)

lineWidth直译为“线宽”,即路径中心到两边的距离,也就是线条的粗细。lineWidth属性的值必须为正数,默认为1.0。

【示例1】在本示例中,使用for循环从画布上方到下方绘制了12条线宽依次递增的直线段。

以上代码在Chrome浏览器中的运行结果如图18-30所示。

图18-30 lineWidth示例

2.lineCap(设置端点样式)

lineCap属性的值用于设置线段端点的样式,包括以下3种:butt、round和square,默认值为butt。

【示例2】在本示例中,从上到下绘制了3条蓝色的直线段,并依次设置上述3种属性值,两侧有两条红色的参考线,这样可以更加清楚地观察端点样式的区别。

以上代码在Chrome浏览器中的运行结果如图18-31所示,可以看到这3种端点样式从上到下依次为平头、圆头和方头。

图18-31 lineCap示例

3.lineJoin(设置连接处样式)

lineJoin属性的值用于设置两条线段连接处的样式,包括以下3种:round、bevel和miter,默认值为miter。

【示例3】在本示例中,从左到右绘制了3条蓝色的折线,并依次设置上述3种属性值,观察拐角处(即直线段连接处)样式的区别。

以上代码在Chrome浏览器中的运行结果如图18-32所示。

图18-32 lineJoin示例

4.miterLimit(设置绘制交点的方式)

miterLimit属性的值用于设置两条线段连接处交点的绘制方式,当宽线条使用lineJoin属性并将其值设置为miter时,如果绘制两条线段并以锐角相交,则所得到的斜面有可能会非常长。当斜面过长时,则图形就会显得不协调。miterLimit属性的作用是为斜面的长度设置一个上限,默认为10,即规定斜面的长度不能超过线条宽度的10倍。当斜面的长度达到线条宽度的10倍时,就会变为斜角。如果lineJoin属性值为round或bevel时,miterLimit属性无效。

【示例4】通过本示例,可以观察当角度和miterLimit属性值发生变化时斜面长度的变化。在运行代码之前,也可以将miterLimit属性值改为固定值,以观察不同的值产生的结果。

以上代码在Chrome浏览器中的运行结果如图18-33所示。

图18-33 miterLimit示例

18.6.2 绘制线性渐变

渐变是在各种绘图软件中经常见到的一种为图形填充颜色或描边的方式,在Canvas中也可以绘制线性或径向的渐变。如果要绘制线性渐变,首先需要使用createLinearGradient()方法创建canvasGradient对象,然后使用addColorStop()方法进行上色。createLinearGradient()方法的用法如下:

     context.createLinearGradient(x1,y1,x2,y2);

其中参数x1、y1为渐变的起点,x2、y2为渐变的终点。例如可以像下面这样来创建一个canvasGradient对象。

     var lineargradient=ctx.createLinearGradient(20,20,150,150);

然后即可使用addColorStop()方法定义色标的位置并进行上色。

     addColorStop(position,color)

其中参数position为渐变中色标的相对位置(或称“偏移值”),必须是一个从0至1的浮点值。渐变起点的偏移值为0,终点的偏移值为1。如果position值为0.5,则表示色标会出现在渐变的正中间。

【示例】下面通过示例来演示如何绘制线性渐变。在本例中共添加了8个色标,分别为红、橙、黄、绿、青、蓝、紫、红。

以上代码在Chrome浏览器中的运行结果如图18-34所示。

图18-34 绘制线性渐变

使用addColorStop()方法可以添加多个色标,色标的添加也并非一定要从0位置开始到1位置结束,而是可以在0~1之间任意添加,例如,从0.3处开始设置一个蓝色色标,再在0.5处设置一个红色色标,则从0~0.3都会填充为蓝色。从0.3~0.5为蓝色到红色的渐变,从0.5~1处则填充为红色。上面的示例中没有使用strokeStyle属性,但要说明的是,这个属性同样可以接受Canvas渐变对象。

18.6.3 绘制径向渐变

如果要绘制径向渐变,则首先需要使用createRadialGradient()方法创建canvasGradient对象,然后使用addColorStop()方法进行上色。createRadialGradient()方法的用法如下:

     context.createRadialGradient(x1,y1,r1,x2,y2,r2);

其中参数x1、y1、r1定义一个以(x1,y1)为原点、半径为r1的圆,x2、y2、r2定义一个以(x2,y2)为原点、半径为r2的圆。例如可以像下面这样来创建一个canvasGradient对象以用于绘制径向渐变。然后即可使用addColorStop()方法定义色标的位置并进行上色。

【示例】下面通过示例来演示如何绘制径向渐变。

     var radialgradient=ctx.createRadialGradient(100,100,30,100,100,200);

以上代码在Chrome浏览器中的运行结果如图18-35所示。

图18-35 绘制径向渐变

18.6.4 绘制图案

在多数绘图软件中都有填充图案这一功能,而在Canvas中,createPattern()方法用来实现图案效果,使用起来非常方便,其用法如下:

     context.createPattern(image,type);

其中参数image为要引用的image对象或另一个Canvas对象,type是所引用对象的平铺类型,必须为下面的字符串值之一。

☑ repeat:同时沿x轴与y轴方向平铺。

☑ repeat-x:沿x轴方向平铺。

☑ repeat-y:沿y轴方向平铺。

☑ no-repeat:不平铺。

创建图案的步骤与创建渐变有些类似,需要先创建出一个pattern,然后再将其赋予fillStyle属性或strokeStyle属性。

【示例】在该示例中,以一幅png格式的图像作为image对象用于创建图案,平铺方式为同时沿x轴与y轴方向平铺。

以上代码在Chrome浏览器中的运行结果如图18-36所示。

图18-36 绘制图案

18.6.5 设置图形的透明度

在前面绘制图形的示例中,已经接触过如何使用globalAlpha属性设置图形的透明度,该方法适合为大量图形设置相同的透明度。除了使用globalAlpha属性之外,还可以通过设置色彩透明度的参数来为图形设置不同的透明度,这种方法相对于使用globalAlpha属性来说,更加灵活方便一些。

使用rgba()方法可以设置具有透明度的颜色,其用法如下:

     rgba(R,G,B,A)

其中R、G、B将颜色的红色、绿色和蓝色成分指定为0~255之间的十进制整数,A把alpha(不透明)成分指定为0.0~1.0之间的一个浮点数值,0.0为完全透明,1.0为完全不透明。例如,可以用"rgba(255,0,0,0.5)"表示半透明的完全红色。

【示例】本示例是前面的矩阵变换示例修改而来,从中可以看出用rgba设置透明度的灵活性和可操作性。

以上代码在Chrome浏览器中的运行结果如图18-37所示。

图18-37 用rgba设置透明度

18.6.6 创建阴影

如果要在Canvas中创建阴影效果,需要用到下面这4个属性:shadowOffsetX、shadowOffsetY、shadowBlur、shadowColor,其用法如下:

     context.shadowOffsetX=float;context.shadowOffsetY=float;context.shadowBlur=float;context.shadowColor=color;

其中shadowOffsetX为阴影的水平偏移,shadowOffsetY为阴影的垂直偏移,默认值都是0,正值表示向下或向右延伸,负值表示向上或向左延伸。shadowBlur为阴影羽化的程度,默认值为0,其数值与像素数量无关,也不受矩阵变换的影响。shadowColor为阴影的颜色,可以指定为一个CSS字符串或Web样式字符串,并且可以包含一个alpha部分来表示透明度,默认值是黑色。

【示例】下面通过示例来演示如何创建文字阴影效果。

以上代码在Chrome浏览器中的运行结果如图18-38所示。

图18-38 创建阴影

18.7 绘制文字

在18.6.6节的示例中用到了fillText()方法来绘制文字,本节详细介绍在Canvas中绘制文字的具体方法。绘制文字使用的是fillText()方法和strokeText()方法,分别用于以填充方式和轮廓方式绘制文字。

18.7.1 绘制填充文字

如果要以填充方式绘制文字,可以用fillText()方法,其用法如下:

     context.fillText(text,x,y,[maxWidth]);

其中text为要绘制的字符串,x、y为绘制文字的横坐标与纵坐标,maxWidth为可选参数,表示显示文字时的最大宽度。如果要绘制的字符串宽度大于指定的最大宽度,字体就会被调整为更“瘦”的字体(如果字体支持横向压缩)或更小的字体。

【示例】以下代码在Chrome浏览器中的运行结果如图18-39所示。

图18-39 绘制填充文字

18.7.2 设置文字属性

在18.7.1节的示例中用到了有关文字的一些属性,下面介绍这些属性以及未在上面出现的其他属性的用法。

☑ font:用于指定正在绘制的文字的样式,其语法与CSS字体样式的指定方法相同。如果要在绘制文字时改变字体样式,只需要更改这个属性的值即可。默认的字体样式为10px sans-serif。例如,可以像下面这样来指定字体样式。

     context.font="20pt Times new roman";

☑ textAlign:用于指定正在绘制的文字的对齐方式,有left、right、center、start、end 5种对齐方式,默认值为start。

▶ left:左对齐。

▶ right:右对齐。

▶ center:居中对齐。

▶ start:如果文字从左到右排版则左对齐,从右到左排版则右对齐。

▶ end:如果文字从右到左排版则左对齐,从左到右排版则右对齐。

☑ textBaseline:用于指定正在绘制的文字的基线,有top、hanging、middle、alphabetic、ideographic、bottom 6种属性值,默认值为alphabetic。

▶ top:文本基线与字元正方形空间顶部对齐。

▶ hanging:文本基线是悬挂的基线,当前不支持。

▶ middle:文本基线位于字元正方形空间的中间位置。

▶ alphabetic:指定文本基线为通常的字母基线。

▶ ideographic:指定文本基线为表意字基线,即如果表意字符的主体突出到字母基线的下方,则表意字基线与表意字符的底部对齐。

▶ bottom:文本基线与字元正方形空间底部的边界框对齐。因为表意基线不能识别下行字符,故可用此种基线来与表意字基线相区分。

当前许多支持HTML5的浏览器尚不支持某些属性值,如hanging、ideographic。

18.7.3 绘制轮廓文字

如果要以轮廓方式绘制文字,可以用strokeText()方法,其用法如下:

     context.strokeText(text,x,y,[maxWidth]);

其中的参数与fillText()相同,在此不再多作解释。

【示例】下面是绘制轮廓文字的一个示例。

以上代码在Chrome浏览器中的运行结果如图18-40所示。

图18-40 绘制轮廓文字

18.7.4 测量文字宽度

使用measureText()方法可以测量当前所绘制文字中指定文字的宽度,该方法会返回一个TextMetrics对象,使用该对象的width属性可以得到指定文字参数后所绘制文字的总宽度,其用法如下:

     metrics=context. measureText(text);

其中的参数text为要绘制的文字。

【示例】下面是测量文字宽度的一个示例。

以上代码在Chrome浏览器中的运行结果如图18-41所示。

图18-41 测量文字宽度

18.8 嵌入图像

在Canvas中不仅可以绘制各种各样的图形,还可以直接引入图像。引入的图像可以改变其大小,可用于创建图像切片、进行图片合成等。Canvas支持多种图像格式,如PNG、GIF、JPEG等,其他的canvas元素也可以作为图像的来源。

18.8.1 向Canvas中引入图像

如果要向Canvas中引入图像,需要经过两个步骤:第一步是确定图像来源,第二步是使用drawImage()方法将图像绘制到Canvas中。

确定图像来源可以有以下4种方式,从中选择一种合适的方式即可。

☑ 页面内的图片:如果已知图片元素的ID,则可以通过document.images集合、document.getElementsByTagName()方法或document.getElementById()方法获取页面内的该图片元素。

☑ 其他canvas元素:可以通过document.getElementsByTagName()方法或document.getElementById()方法获取已经准备好的canvas元素。例如,可以用这种方法为一个比较大的Canvas生成缩略图。

☑ 用脚本创建一个新的Image对象:使用脚本可以从零开始创建一个新的Image对象,不过这种方法存在一个缺点,即如果图像文件来源于网络且体积较大,则会花费较长的时间来装载,所以如果不希望因为图像文件装载而导致的漫长的等待,需要做好预装载的工作。

☑ 使用data:url方式引用图像:这种方法允许用Base64编码的字符串来定义一个图片,优点是图片可以即时使用,不必等待装载,而且迁移也非常容易。缺点是无法缓存图像,所以如果图片较大,则不太适宜用这种方法,因为这会导致嵌入的url数据相当庞大。

在使用脚本创建新Image对象时,其方法如下:

     var img=new Image();    //创建新的Image对象img.src='Image1.png';   //设置图像路径

如果要解决图片预装载的问题,则可以使用下面的方法,即使用onload事件一边装载图像一边执行绘制图像的函数。

不管采用什么获取图像来源,之后的工作都是使用drawImage()方法将图像绘制到Canvas中。drawImage()方法有以下3种用法。

     context.drawImage(image,x,y);context.drawImage(image, x, y, width, height);context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh);

第一种是最基础和最简单的方法,其中image是引入的image对象或Canvas对象,x和y目标是Canvas中要绘制到的起始位置的坐标。

【示例】本示例演示了如何使用上述两个步骤将图像引入到Canvas中。至于第二种和第三种drawImage()方法,将在后续的小节中单独介绍。

以上代码在Chrome浏览器中的运行结果如图18-42所示。可以看到,通过引入外部图像作为文字的背景,可以省下许多代码。

图18-42 向Canvas中引入图像

18.8.2 改变图像大小

许多时候,需要在某个特定位置显示特定大小的图像,而且更新时希望不同图像文件显示在网页中的大小保持原来的统一尺寸,以保证网页布局与美观不受影响,这时需要用脚本动态改变图像的大小。当然,在其他场合,也可能需要改变图像大小以适应网页布局或其他功能的需要。

drawImage()方法(第2种用法)用于使图片按指定的大小显示,其用法如下:

     context.drawImage(image, x, y, width, height);

其中width和height分别是图像在canvas中显示的宽度和高度。

【示例】可以将18.8.1节示例中的代码稍做修改,以使得引入的图像调整为指定的大小,这样做的好处是可以让图像迁就页面布局。

以上代码在Chrome浏览器中的运行结果如图18-43所示。

18.8.3 创建图像切片

drawImage()方法(第3种用法)用于创建图像切片,其用法如下:

     context.drawImage(image,sx,sy,sw,sh,dx,dy,dw,dh);

其中image参数与前两种用法相同,其余8个参数可以参考图18-44。sx、sy为源图像被切割区域的起始坐标,sw、sh为源图像被切下来的宽度和高度,dx、dy为被切割下来的源图像要放置到目标Canvas的起始坐标,dw、dh为被切割下来的源图像放置到目标Canvas并显示的高度和宽度。

图18-43 改变图像大小

图18-44 其余8个参数的图示

【示例】下面通过一个示例来演示如何创建图像切片。

以上代码在Chrome浏览器中的运行结果如图18-45所示。其中上方显示的是源图像,下方是所创建的图像切片。

图18-45 创建图像切片

第18章 HTML5动画设计相关推荐

  1. HTML5期末大作业:婚庆网站设计——红色的婚庆(18页) HTML5网页设计成品_学生DW静态网页设计代做_web课程设计网页制作

    HTML5期末大作业:婚庆网站设计--红色的婚庆(18页) HTML5网页设计成品_学生DW静态网页设计代做_web课程设计网页制作 常见网页设计作业题材有 个人. 美食. 公司. 学校. 旅游. 电 ...

  2. 期末作业成品代码——红色的婚庆(18页) HTML5网页设计成品_学生DW静态网页设计代做_web课程设计网页制作

    HTML5期末大作业:婚庆网站设计--红色的婚庆(18页) HTML5网页设计成品_学生DW静态网页设计代做_web课程设计网页制作 常见网页设计作业题材有 个人. 美食. 公司. 学校. 旅游. 电 ...

  3. Adobe推出HTML5动画设计工具Edge

    2019独角兽企业重金招聘Python工程师标准>>> HTML5和Flash,是敌对?是共存? 尽管Flash现在依然牢牢占据着网络动画的大半江山,但这种状况终将会被改变. 那么, ...

  4. matlab图形与动画设计 pdf,MATLAB图形与动画设计

    基本信息 书名:MATLAB图形与动画设计 **:36.00元 售价:34.2元,便宜1.8元,折扣95 作者:张德丰,赵书梅,刘国希 出版社:国防工业出版社 出版日期:2009-04-01 ISBN ...

  5. appinventor HTML5,App Inventor编程教程-第18课-创建动画应用

    本章将讨论另一类应用--包含简单动画(会移动的物体)的应用.你将学习用App Inventor创建二维游戏的基本知识,包括熟练使用精灵组件,以及处理像两个物体碰撞这样的事件. 当在电脑屏幕上看到一个平 ...

  6. html5 游戏 动画设计,11款效果惊艳的HTML5动画应用

    11款效果惊艳的HTML5动画应用 来源:极客头条 HTML5真的很棒,我们这个网站也每天在为大家分享很多炫酷而实用的HTML5和CSS3应用.今天要分享的有很多效果惊艳而且好玩的HTML5动画应用, ...

  7. html5 游戏 动画设计,设计师必看的10个HTML5动画工具

    如果你想用令人难以置信的动画创建引人注目的网站的话,那么这里为设计师精心挑选了一些必备的HTML5动画工具.HTML5是设计师用来打造时尚网站的最流行的编程语言之一.在过去三年内,这种编程语言的使用人 ...

  8. 原生html5网页设计,HTML5网页设计教程

    HTML5网页设计教程 编辑 锁定 讨论 上传视频 <HTML5网页设计教程>是2017年1月清华大学出版社出版的图书,作者是孙甲霞.吕莹莹.李学勇.金松林.郑颖. 书    名 HTML ...

  9. 推荐十款非常优秀的 HTML5 在线设计工具

    网络有很多优秀的设计和开发工具可能大家都不知道,因此这篇文章就向设计师推荐十款优秀 HTML5 在线工具,这些工具能够帮助设计师们设计出更有创意的作品.随着 HTML5 技术的不断成熟,网络上涌现出越 ...

最新文章

  1. PHP开发错误锦集(持续更新)
  2. python输入参数改变图形_Python基于Tensor FLow的图像处理操作详解
  3. mysql select 区分大小写,MySql查询不区分大小写解决方案(两种)
  4. tomcat work目录的作用就是编译每个项目里的jsp文件为java文件如果项目没有jsp页面则这个项目文件夹为空...
  5. oracle Hash Join及三种连接方式
  6. JAVA多线程和并发基础面试问答(转载)
  7. 王者荣耀微信哪个服务器人最少,王者荣耀:微信区王者人数锐减,大神们都去哪了?这些原因很真实...
  8. 去除标签_有效去除“狗皮膏药”标签,快学起来吧
  9. android--多线程,android多线程
  10. php读取pdf文件乱码_PHP 读取PDF文件内容之PdfParser
  11. mysql创建gbk库_MYSQL创建utf-8和GBK格式数据库_MySQL
  12. 【网络信息安全】网络信息安全基础
  13. ios8.1.3 刷机8.2beta越狱 真机调试 一起喝成
  14. 思科模拟器Cisco Packet Tracer的下载与安装
  15. android虚拟应用沙箱,Android的SandBox(沙箱)
  16. 华为路由器PPP与MP-PPP的配置实例
  17. 培养好习惯是很难,但也有方法
  18. TN、IPS、VA面板区别
  19. 计算机组成原理实验内存读数,计算机组成原理实验八内存系统实验(3页)-原创力文档...
  20. 编程辅助工具推荐:图片工具snipaste

热门文章

  1. 魅族android n怎么更新,给力!魅族安卓7.0升级计划正式启动:史上最大规模
  2. 使用PHPEXCEL导入数据到数据库
  3. 【ClickHouse】row_number() over (partition by)的几种实现方法
  4. 两个YATE服务器互联的实现
  5. 分布式光伏联网设备推荐——4G/5G工业路由器/有线工业路由器
  6. 华为鸿蒙os官网正式上线,华为鸿蒙OS官网正式上线:提供源码下载 首批支持128KB~1...
  7. 虚拟养老院打造智慧养老新模式,虚拟养老院助力智慧养老发展-新导智能
  8. uniapp,小程序封装请求接口
  9. DappLooker质押数据面板解读
  10. DLP RGB结构光投影光源 IMSTL_M20_V2