从0到1:HTML5 Canvas动画开发

978-7-115-53706-5
作者: 莫振杰
译者:
编辑: 罗芬

图书目录:

详情

作者根据自己多年的前后端开发经验,详尽介绍了HTML5 Canvas 动画开发技术。 本书分为两大部分:第一部分介绍Canvas 基础知识,主要包括Canvas 概述、直线图形、曲线图形、线条操作、文本操作、图片操作、变形操作、像素操作、渐变与阴影、Canvas 路径、Canvas 状态及其他应用; 第二部分介绍Canvas 进阶知识,主要包括事件操作、物理动画、边界检测、碰撞检测、用户交互、高级动画、Canvas 游戏开发、Canvas 图表库。 此外,本书还配备了书中所有案例的源代码和PPT 教学课件,以方便学校老师教学。本书适合作为前端开发人员的参考书,也可以作为各类院校相关专业的教材及教学参考书。

图书摘要

从0到1:HTML5 Canvas动画开发 全彩版

莫振杰 著

人民邮电出版社

北京

图书在版编目(CIP)数据

从0到1:HTML5 Canvas动画开发/莫振杰著.--北京:人民邮电出版社,2020.6

ISBN 978-7-115-53706-5

Ⅰ.①从… Ⅱ.①莫… Ⅲ.①超文本标记语言一程序设计 Ⅳ.①TP312.8

中国版本图书馆CIP数据核字(2020)第052314号

◆著 莫振杰

责任编辑 罗芬

责任印制 马振武

◆人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 https://www.ptpress.com.cn

北京东方宝隆印刷有限公司印刷

◆开本:787×1092 1/16

印张:21

字数:577千字  2020年6月第1版

印数:1-2500册  2020年6月北京第1次印刷

定价:89.80元

读者服务热线:(010)81055410  印装质量热线:(010)81055316

反盗版热线:(010)81055315

广告经营许可证:京东工商广登字20170147号

内容提要

作者根据自己多年的前后端开发经验,详尽介绍了HTML5 Canvas动画开发技术。

本书分为两大部分:第一部分介绍 Canvas 基础知识,主要包括 Canvas 概述、直线图形、曲线图形、线条操作、文本操作、图片操作、变形操作、像素操作、渐变与阴影、Canvas路径、Canvas状态及其他应用;第二部分介绍Canvas进阶知识,主要包括事件操作、物理动画、边界检测、碰撞检测、用户交互、高级动画、Canvas游戏开发、Canvas图表库。

此外,本书还配备了书中所有案例的源代码和PPT教学课件,以方便学校老师教学。本书适合作为前端开发人员的参考书,也可以作为各类院校相关专业的教材及教学参考书。

其他

如果你想要快速上手前端开发,又岂能错过“从0到1”系列?

这是一本非常有个性的书,学起来非常轻松!当初看到这本书时,我们很惊喜,简直像是发现了新大陆。

你随手翻几页,就能看出来作者真的是用“心”去写的。

作为忠实的读者,很幸运能够参与本书的审稿及设计。事实上,对于这样一本难得的好书,相信你看了之后,也会非常乐意帮忙将它完善得更好。

——五叶草团队

前言

一本好书不仅可以让读者学得轻松,更重要的是可以让读者少走弯路。如果你需要的不是大而全,而是恰到好处的前端开发教程,那么不妨试着看一下这本书。

本书和“从0到1”系列中的其他图书,大多都是源于我在绿叶学习网分享的超人气在线教程。由于教程的风格独一无二、质量很高,因而累计获得超过100000读者的支持。更可喜的是,我收到过几百封的感谢邮件,大多来自初学者、已经工作的前端工程师,还有不少高校老师。

我从开始接触前端开发时,就在记录作为初学者所遇到的各种问题。因此,我非常了解初学者的心态和困惑,也非常清楚初学者应该怎样才能快速而无阻碍地学会前端开发。我用心总结了自己多年的学习和前端开发经验,完全站在初学者的角度而不是已经学会的角度来编写本书。我相信,本书会非常适合零基础的读者轻松地、循序渐进地展开学习。

之前,我问过很多小伙伴,看“从0到1”这个系列图书时是什么感觉。有人回答说:“初恋般的感觉。”或许,本书不一定十全十美,但是肯定会让你有初恋般的怦然心动。

配套习题

每章后面都有习题,这是我和一些有经验的前端工程师精心挑选、设计的,有些来自实际的前端开发工作和面试题。希望小伙伴们能认真完成每章练习,及时演练、巩固所学知识点。习题答案放于本书的配套资源中,具体下载方式见下文。

配套网站

绿叶学习网(www.lvyestudy.com)是我开发的一个开源技术网站,该网站不仅可以为大家提供丰富的学习资源,还为大家提供了一个高质量的学习交流平台,上面有非常多的技术“大牛”。小伙伴们有任何技术问题都可以在网站上讨论、交流,也可以加QQ群讨论交流:519225291、593173594(只能加一个QQ群)。

配套资源下载及使用说明

本书的配套资源包括习题答案、源码文件、配套PPT教学课件。扫描下方二维码,关注微信公众号“职场研究社”并回复“53706”,即可获得资源下载方式。

特别鸣谢

本书的编写得到了很多人的帮助。首先要感谢人民邮电出版社的赵轩编辑和罗芬编辑,有他们的帮助本书才得以顺利出版。

感谢五叶草团队的一路陪伴,感谢韦雪芳、陈志东、秦佳、程紫梦、莫振浩,他们花费了大量时间对本书进行细致的审阅,并给出了诸多非常棒的建议。

最后要感谢我的挚友郭玉萍,她为“从0到1”系列图书提供了很多帮助。在人生的很多事情上,她也一直在鼓励和支持着我。认识这个朋友,也是我这几年中特别幸运的事。

由于水平有限,书中难免存在不足之处。小伙伴们如果遇到问题或有任何意见和建议,可以发送电子邮件至lvyestudy@foxmail.com,与我交流。此外,也可以访问绿叶学习网(www. lvyestudy.com),了解更多前端开发的相关知识。

作者

第1章 Canvas概述

1.1 Canvas是什么

1.1.1 Canvas简介

在HTML5之前,为了让页面获得绚丽多彩的效果,我们在很多情况下都是借助“图片”来实现的。然而图片体积大、加载速度慢,使用图片的代价就是降低了页面的性能。为了应对日渐复杂的Web应用开发,W3C在HTML5标准中引入了Canvas这一门技术。

Canvas,又称“画布”,是HTML5的核心技术之一。HTML5中新增了一个Canvas元素,我们常说的Canvas技术,指的就是使用Canvas元素结合JavaScript来绘制各种图形的技术。

既然Canvas是HTML5的核心技术之一,那它都有哪些厉害之处呢?

绘制图形

使用Canvas可以绘制各种基本图形,如矩形、曲线、圆等,也可以绘制各种复杂绚丽的图形,如图1-1所示。

绘制图表

很多公司的数据展示都离不开图表,使用Canvas可以绘制满足各种需求的图表,如图1-2所示。

动画效果

使用Canvas,我们也可以制作各种华丽的动画效果,非常棒!这也是Canvas给我们带来的一大乐趣,如图1-3所示。

游戏开发

HTML5在游戏开发领域具有举足轻重的地位,现在我们也可以使用Canvas来开发各种游戏。这几年非常“火”的游戏,如《捕鱼达人》《围住神经猫》等,都是使用HTML5 Canvas开发的,如图1-4所示。

此外,Canvas技术是一门纯JavaScript操作的技术,因此大家需要具备JavaScript入门知识。对于JavaScript的学习,可以关注“从0到1”系列的另一本图书:《从0到1:JavaScript快速上手》。

1.1.2 Canvas与SVG

HTML5有两个主要的2D图形技术:Canvas和SVG。事实上,Canvas和SVG是两门完全不同的技术,两者具有以下区别。

Canvas是使用JavaScript动态生成的,SVG是使用XML静态描述的。

Canvas是基于“位图”的,适用于像素处理和动态渲染,放大图形会使图形失真,如图1-5所示;SVG是基于“矢量”的,不适用于像素处理和适合静态描述,放大图形也不会使图形失真,如图1-6所示。也就是说,使用Canvas绘制出来的是一个“位图”,而使用SVG绘制出来的是一个“矢量图”。

若发生修改,使用Canvas需要重绘,而使用SVG不需要重绘。

Canvas与SVG的关系,简单来说,就像“美术与几何”的关系一样。

此外,并非Canvas比SVG有用,也并非SVG比Canvas有用,它们各自用于不同场合。在实际开发中,我们应该根据需求选择其中一种。

当然,这里只是简单介绍了Canvas与SVG的区别,如果想要真正了解,我们还得深入学习。最后给小伙伴一个小小的建议:很多人接触新技术的时候,喜欢在第1遍学习中就把每一个细节都抠清楚,事实上这是效率最低的学习方法。其实,如果有些东西我们实在没办法理解,那就直接跳过,等学到后面或者看第2遍的时候,自然而然就懂了。

1.2 Canvas元素

HTML5 Canvas,简单来说,就是一门使用JavaScript来操作Canvas元素的技术。使用Canvas元素来绘制图形,需要以下3步。

① 获取canvas对象。

② 获取上下文环境对象context。

③ 开始绘制图形。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script type="text/javascript">

window.onload = function () {

//1、获取canvas对象

var cnv = document.getElementById("canvas");

//2、获取上下文环境对象context

var cxt = cnv.getContext("2d");

//3、开始绘制图形

cxt.moveTo(50, 100);

cxt.lineTo(150, 50);

cxt.stroke();

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图1-7所示。

分析

在Canvas中,我们使用document.getElementById()方法来获取Canvas对象(这是一个DOM对象),然后使用Canvas对象的getContext("2d")方法获取上下文环境对象context,最后使用context对象的属性和方法来绘制各种图形。

1.2.1 Canvas元素简介

Canvas是一个行内块元素(即inline-block),我们一般需要指定其3个属性:id、width和height。width和height分别用于定义Canvas元素的宽度和高度。默认情况下,Canvas元素的宽度为300px(Pixel,像素),高度为150px。

对于Canvas的宽度和高度,我们有两种方法来定义:一是在HTML属性中定义,二是在CSS样式中定义。但是在实际开发中,我们一定不要在CSS样式中定义,而应该在HTML属性中定义。为什么呢?我们先来看一个例子。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<style type="text/css">

canvas

{

width:200px;

height:150px;

}

</style>

<script type="text/javascript">

window.onload = function () {

var cnv = document.getElementById("canvas");

var str = "canvas的宽度为:" + cnv.width + ",高度为:" + cnv.height;

alert(str);

}

</script>

</head>

<body>

<canvas id="canvas" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图1-8所示。

分析

从这个例子我们可以看出:如果在CSS样式中定义,Canvas元素的宽度和高度是默认值,而不是所定义的宽度和高度,这样我们就无法获取Canvas元素正确的宽度和高度。获取Canvas元素实际的宽度和高度是Canvas开发中最常用的操作,因此对于Canvas元素的宽度和高度,我们一定要在HTML属性中定义,而不是在CSS样式中定义。

1.2.2 Canvas对象

在Canvas中,我们使用document.getElementById()来获取Canvas对象。Canvas对象常用的属性和方法如表1-1和表1-2所示。

也就是说,我们可以使用cnv.width和cnv.height分别获取Canvas对象的宽度和高度,可以使用cnv.getContext("2d")来获取Canvas 2D上下文环境对象,也可以使用toDataURL()来获取Canvas对象产生的位图的字符串。在这里,cnv指的是Canvas对象。

对于toDataURL()方法,小伙伴们暂时不需要深入了解,在后面的章节中会给大家详细介绍。这里我们要认真学习getContext("2d")方法。在Canvas中,我们使用getContext("2d")来获取Canvas 2D上下文环境对象,这个对象又被称为context对象。后面章节接触的所有图形的绘制,使用的都是context对象的属性和方法,我们要特别清楚这一点。当然,现在不理解没关系,学到后面再回过头来看看这段话就懂了。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script type="text/javascript">

window.onload = function () {

var cnv = document.getElementById("canvas");

var str = "Canvas的宽度为:" + cnv.width + ",高度为:" + cnv.height;

alert(str);

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="160" style="border:1px dashed gray"></canvas>

</body>

</html>

预览效果如图1-9所示。

特别要注意一点:在本书中所有图形的绘制,使用的都是context对象(上下文环境对象)的属性和方法。

【解惑】

1.我们可以使用getContext("2d")来实现2D绘图,那是不是意味着可以使用getContext ("3d")来实现3D绘图呢?

HTML5 Canvas暂时只提供2D绘图API,3D绘图可以使用HTML5中的WebGL实现。不过3D绘图一直以来都是HTML5中的“黑科技”,技术要求高并且难度大。等学完了这本书,有兴趣的小伙伴可以关注绿叶学习网的WebGL教程。

2.对于IE浏览器来说,暂时只有IE9以上版本支持HTML5 Canvas,那怎么处理IE7和IE8的兼容性问题呢?

对于IE7和IE8,我们可以借助“explorercanvas”这个扩展来解决。该扩展下载地址为:https://github.com/arv/explorercanvas。

我们只需要在页面中像引入外部JavaScript文件那样引入“excanvas.js”就可以了,代码如下。

<!--[if IE]>

<script src="excanvas.js"></script>

<![end if]-->

不过要跟大家说明一下,低版本的IE浏览器即使引入了“excanvas.js”来使用Canvas,在功能上也会有很多限制,如无法使用fillText()方法等。

3.除了这本书,还有哪些值得推荐的Canvas教程?

建议小伙伴们多看看W3C官方网站的Canvas开发文档,因为这是比较权威的参考资料。W3C官网地址:www.w3.org/TR/2dcontext/。

第2章 直线图形

2.1 直线图形简介

在Canvas中,基本图形有两种:直线图形和曲线图形。其中,常见的直线图形有以下3种。

直线。

矩形。

多边形。

这一章我们先来学习Canvas中的直线图形。

2.2 直线

2.2.1 Canvas坐标系

在学习之前,我们先来介绍一下Canvas使用的坐标系,这是学习Canvas最基本的前提。

我们经常见到的坐标系是数学坐标系,不过Canvas使用的坐标系是W3C坐标系,这两种坐标系唯一的区别在于y轴正方向的不同,如图2-1所示。

数学坐标系:y轴正方向向上。

W3C坐标系:y轴正方向向下。

小伙伴们一定要记住:W3C坐标系的y轴正方向是向下的。很多人学到后面对Canvas中的某些代码感到很困惑,那是因为他们没有清楚地意识到这一点。

数学坐标系一般用于数学上的应用,而在前端开发中几乎所有涉及坐标系的技术使用的都是W3C坐标系,这些技术包括CSS3、Canvas、SVG等。了解这一点,以后在学习CSS3或者SVG的时候,我们一下子就可以串起很多知识。

2.2.2 直线的绘制

在Canvas中,我们可以将moveTo()和lineTo()这两个方法配合使用来画直线。利用这两个方法,我们可以画一条直线,也可以同时画多条直线。

1.一条直线

语法

cxt.moveTo(x1, y1);

cxt.lineTo(x2, y2);

cxt.stroke();

说明

cxt表示上下文环境对象context。

(x1,y1)表示直线“起点”的坐标。moveTo(x1,y1)的含义是“将画笔移到点(x1,y1)位置,然后开始绘图”。

(x2,y2)表示直线“终点”的坐标。lineTo(x2,y2)的含义是“使用画笔从起点(x1,y1)开始画直线,一直画到终点(x2,y2)”。

对于moveTo()和lineTo()这两个方法,我们从英文含义角度更容易理解和记忆。

cxt.moveTo(x1, y1);

cxt.lineTo(x2, y2);

上面两句代码仅仅是确定直线的“起点坐标”和“终点坐标”,但是实际上画笔还没“动”。因此,我们还需要调用上下文环境对象的stroke()方法才有效。

使用Canvas画直线,跟我们平常用笔在纸张上画直线的道理一样,都是先确定直线起点(x1,y1)与终点(x2,y2),然后再用笔连线,即stroke()。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id){

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.moveTo(50, 100);

cxt.lineTo(150, 50);

cxt.stroke();

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-2所示。

分析

在这个例子中,我们定义了一个获取DOM对象元素的函数$$(id),这样减少了重复代码量,使得思路更加清晰。记住,Canvas中使用的坐标系是W3C坐标系,这个例子的分析思路如图2-3所示。

2.多条直线

使用moveTo()和lineTo()这两个方法可以画一条直线。其实,如果我们想同时画多条直线,也是使用这两个方法。

语法

cxt.moveTo(x1, y1);

cxt.lineTo(x2, y2);

cxt.lineTo(x3,y3);

……

cxt.stroke();

说明

lineTo()方法是可以重复使用的:第1次使用lineTo()后,画笔将自动移到终点;第2次使用lineTo()后,Canvas会以“上一个终点的坐标”作为第2次调用的起点,然后再开始画直线,依此类推。我们还是先来看一个例子,这样更容易理解。

举例:画两条直线

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id){

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.moveTo(50,50);

cxt.lineTo(100,50);

cxt.moveTo(50,100);

cxt.lineTo(100,100);

cxt.stroke();

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-4所示。

分析

记住,moveTo()的含义是“将画笔移到该点的位置,然后开始绘图”。lineTo()的含义是“将画笔从起点开始画直线,一直到终点”。

如果我们将cxt.moveTo(50,100);改为cxt.lineTo(50,100);,预览效果如图2-5所示。大家根据这个例子,仔细琢磨一下moveTo()与lineTo()两个方法的区别。

举例:用直线画一个三角形

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id){

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.moveTo(50, 100);

cxt.lineTo(150, 50);

cxt.lineTo(150, 100);

cxt.lineTo(50, 100);

cxt.stroke();

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-6所示。

分析

这里使用moveTo()与lineTo()方法画了一个三角形。在画三角形之前,我们先要确定三角形3个顶点的坐标。

举例:用直线画一个矩形

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id){

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.moveTo(50, 100);

cxt.lineTo(50, 50);

cxt.lineTo(150, 50);

cxt.lineTo(150, 100);

cxt.lineTo(50, 100);

cxt.stroke();

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-7所示。

分析

这里使用moveTo()和lineTo()方法画了一个矩形。在画矩形之前,我们也是要先确定矩形的4个顶点坐标(这几个坐标值不是随便来的,而是计算出来的)。

在Canvas中,使用moveTo()和lineTo()方法可以画三角形、矩形、多边形等。在实际开发中,对于三角形和多边形,我们都用moveTo()和lineTo()方法来实现。但是对于矩形来说, Canvas为我们提供了一套更为简单的方法,我们将在下一节给大家详细介绍。

2.3 矩形

从上一节我们知道,可以配合使用moveTo()和lineTo()方法来画一个矩形。但是这种画矩形的方法代码量过多,因此在实际开发中并不推荐使用。

对于绘制矩形,Canvas另外为我们提供了独立的方法来实现。在Canvas中,矩形分为两种:描边矩形和填充矩形。

2.3.1 描边矩形

在Canvas中,我们可以配合使用strokeStyle属性和strokeRect()方法,来画一个描边矩形。

语法

cxt.strokeStyle = 属性值;

cxt.strokeRect(x,y,width,height);

说明

strokeStyle是context对象的一个属性,strokeRect()是content对象的一个方法。大家要区分什么叫属性,什么叫方法。

1.strokeStyle属性

strokeStyle属性取值有3种:颜色值、渐变色和图案。对于strokeStyle属性取值为渐变色和图案的情况,我们会在后续章节详细讲解。现在,我们先来看一下strokeStyle属性取值为颜色值的几种情况。

cxt.strokeStyle = "#FF0000"; //十六进制颜色值

cxt.strokeStyle = "red"; //颜色关键字

cxt.strokeStyle = "rgb(255,0,0)"; //rgb颜色值

cxt.strokeStyle = "rgba(255,0,0,0.8)"; //rgba颜色值

2.strokeRect()方法

strokeRect()方法用于确定矩形的坐标,其中(x,y)为矩形左上角点的坐标。注意, Canvas中的坐标,大家一定要根据W3C坐标系来理解,如图2-8所示。此外,width表示矩形的宽度, height表示矩形的高度,默认情况下width和height都是以px为单位的。

我们还要特别注意一点,strokeStyle属性必须在使用strokeRect()方法之前定义,否则strokeStyle属性无效。也就是说,在使用strokeRect()方法画线之前,要把应有的参数(如strokeStyle属性)设置好。Canvas是根据已设置的参数来“画”图形的,其实这跟我们平常画画是一样的道理。在动笔之前,先要确定画的是什么,用什么颜色,然后再用笔画出来。我们总不能在不知道自己想要画什么时,就开始动笔乱画吧!

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id){

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.strokeStyle = "red";

cxt.strokeRect(50, 50, 80, 80);

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-9所示。

分析

当我们将cxt.strokeStyle = "red";和cxt.strokeRect(50, 50, 80, 80);这两句代码位置互换后, strokeStyle属性就不会生效了。大家可以自行在本地编辑器中修改测试一下,看看实际效果。本例的分析思路如图2-10所示。

2.3.2 填充矩形

在Canvas中,我们可以配合使用fillStyle属性和fillRect()方法来画一个填充矩形。

语法

cxt.fillStyle=属性值;

cxt.fillRect(x, y, width, height);

说明

fillStyle是context对象的一个属性,fillRect()是context对象的一个方法。

fillStyle属性跟strokeStyle属性一样,取值也有3种:颜色值、渐变色和图案。

fillRect()方法跟strokeRect()方法一样,用于确定矩形的坐标,如图2-11所示。其中(x,y)为矩形左上角点的坐标,width表示矩形的宽度,height表示矩形的高度。

跟描边矩形一样,填充矩形的fillStyle属性也必须在使用fillRect()方法之前定义,否则fillStyle属性无效。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id){

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.fillStyle = "HotPink";

cxt.fillRect(50, 50, 80, 80);

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-12所示。

分析

当我们将cxt.fillStyle = "HotPink";和cxt.fillRect(50, 50, 80, 80);这两句代码位置互换后, fillStyle属性就不会生效了。大家可以自行在本地编辑器中修改测试一下,看看实际效果。本例的分析思路如图2-13所示。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id) {

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.strokeStyle = "red";

cxt.strokeRect(50, 50, 80, 80);

cxt.fillStyle = "#FFE8E8";

cxt.fillRect(50, 50, 80, 80);

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-14所示。

分析

在这个例子中,我们同时画了描边矩形和填充矩形。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id) {

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.fillStyle = "HotPink";

cxt.fillRect(50, 50, 80, 80);

cxt.fillStyle = "rgba(0, 0, 255, 0.3)";

cxt.fillRect(30, 30, 80, 80);

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-15所示。

分析

这里我们画了两个矩形:第1个矩形使用了十六进制颜色值;第2个矩形使用了RGBA颜色值。

2.3.3 rect()方法

在Canvas中,如果想要绘制一个矩形,除了使用strokeRect()和fillRect()这两个方法之外,我们还可以使用rect()方法。

语法

rect(x,y,width,height);

说明

x和y为矩形左上角点的坐标,width表示矩形的宽度,height表示矩形的高度,如图2-16所示。

使用strokeRect()、fillRect()和rect()这3种方法都可以画矩形。这3种方法的参数设置是相同的,不同之处在于实现效果。其中,strokeRect()和fillRect()这两个方法在被调用之后,会立即把矩形绘制出来。而rect()方法在被调用之后,并不会立即把矩形绘制出来。只有在使用rect()方法之后再调用stroke()或fill()方法,才会把矩形绘制出来。

·rect()和stroke()

cxt.strokeStyle="red";

cxt.rect(50,50,80,80);

cxt.stroke();

上述代码等价于:

cxt.strokeStyle="red";

cxt.strokeRect(50,50,80,80);

·rect()和fill()

cxt.fillStyle="red";

cxt.rect(50,50,80,80);

cxt.fill();

上述代码等价于:

cxt.fillStyle="red";

cxt.fillRect(50,50,80,80);

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id){

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

//绘制描边矩形

cxt.strokeStyle = "red";

cxt.rect(50, 50, 80, 80);

cxt.stroke();

//绘制填充矩形

cxt.fillStyle = "#FFE8E8";

cxt.rect(50, 50, 80, 80);

cxt.fill();

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-17所示。

2.3.4 清空矩形

在Canvas中,我们可以使用clearRect()方法来清空“指定矩形区域”。

语法

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

说明

x、y分别表示被清空矩形区域左上角点的横、纵坐标,width表示矩形的宽度,height表示矩形的高度。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id){

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.fillStyle = "HotPink";

cxt.fillRect(50, 50, 80, 80);

cxt.clearRect(60, 60, 50, 50);

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-18所示。

分析

这里使用clearRect()方法来清空指定矩形区域。这个例子的分析思路如图2-19所示。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id) {

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.fillStyle = "HotPink";

cxt.fillRect(50, 50, 80, 80);

var btn = $$("btn");

btn.onclick = function () {

cxt.clearRect(0, 0, cnv.width, cnv.height);

}

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas><br />

<input id="btn" type="button" value="清空canvas"/>

</body>

</html>

预览效果如图2-20所示。

分析

cxt.clearRect(0, 0, cnv.width, cnv.height);用于清空整个Canvas。其中,cnv.width表示获取Canvas的宽度,cnv.height表示获取Canvas的高度。“清空整个Canvas”这个技巧在Canvas动画开发中会经常用到,大家一定要记住。至于怎么用,在接下来的章节里,我们会慢慢接触到。

最后再次强调,所有Canvas图形操作的属性和方法都是基于context对象的。

2.4 多边形

通过前面的学习可以知道,我们可以配合使用moveTo()和lineTo()方法来画三角形和矩形。其实在Canvas中,多边形也是使用moveTo()和lineTo()这两个方法画出来的。

如果想要在Canvas中画多边形,我们需要事先在草稿纸或软件中计算出多边形各个顶点的坐标,然后再使用moveTo()和lineTo()方法在Canvas中画出来。

跟矩形不一样,Canvas没有专门用来绘制三角形和多边形的方法。对于三角形以及多边形,我们也是使用moveTo()和lineTo()这两个方法来实现的。

2.4.1 箭头

对于绘制箭头,我们都是事先确定箭头的7个顶点坐标,然后使用moveTo()和lineTo()方法来绘制。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id) {

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.moveTo(40, 60);

cxt.lineTo(100, 60);

cxt.lineTo(100, 30);

cxt.lineTo(150, 75);

cxt.lineTo(100, 120);

cxt.lineTo(100, 90);

cxt.lineTo(40, 90);

cxt.lineTo(40, 60);

cxt.stroke();

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-21所示。

分析

在绘制之前,我们需要计算出箭头各个顶点的坐标。

2.4.2 正多边形

正多边形在实际开发中也经常见到,要想绘制正多边形,我们首先来了解一下最简单的正多边形——正三角形,如图2-22所示。

根据正三角形的特点,我们可以封装一个绘制正多边形的函数:createPolygon()。

举例

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id) {

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

//调用自定义的方法createPolygon()

createPolygon(cxt, 3, 100, 75, 50);

cxt.fillStyle = "HotPink";

cxt.fill();

}

/*

* n:表示n边形

* dx、dy:表示n边形中心坐标

* size:表示n边形的大小

*/

function createPolygon(cxt, n, dx, dy, size) {

cxt.beginPath();

var degree = (2 * Math.PI )/ n;

for (var i = 0; i < n; i++) {

var x = Math.cos(i * degree);

var y = Math.sin(i * degree);

cxt.lineTo(x * size + dx, y * size + dy);

}

cxt.closePath();

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-23所示。

分析

cxt.beginPath();用于开始一条新路径,cxt.closePath();用于关闭路径。对于beginPath()和closePath()这两个方法,我们会在“第10章 Canvas路径”详细介绍,这里不需要深入了解。

在这个例子中,我们定义了一个绘制多边形的函数。对于这个函数,我们可以加入更多的参数,如颜色、边框等,然后可以把它封装到我们的私人图形库。

当我们将createPolygon(cxt, 3, 100, 75, 50);改为createPolygon(cxt, 4, 100, 75, 50);时,预览效果如图2-24所示。

当我们将createPolygon(cxt, 3, 100, 75, 50);改为createPolygon(cxt, 5, 100, 75, 50);时,预览效果如图2-25所示。

当我们将createPolygon(cxt, 3, 100, 75, 50);改为createPolygon(cxt, 6, 100, 75, 50);时,预览效果如图2-26所示。

createPolygon()只能用于绘制正多边形,无法用于绘制不规则多边形。绘制不规则多边形的方法也很简单,都是先确定多边形各个顶点的坐标,然后使用moveTo()和lineTo()慢慢绘制。

2.4.3 五角星

我们来看一下五角星,如图2-27所示。

同样,我们也是先获取各个顶点的坐标,然后使用moveTo()和lineTo()把五角星绘制出来的。根据上面的分析图,我们可以知道∠BOA=36°、∠AOX=18°、∠BOX=54°,然后结合三角函数,我们很容易得出五角星各个顶点的坐标。这个推导过程是简单的,如果小伙伴们的数学已经“还给老师”了,那就没办法了。大家可以自己在草稿中算一下,这里就不详细展开了。

举例

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title></title>

<meta charset="utf-8" />

<script type="text/javascript">

function $$(id) {

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

cxt.beginPath();

for (var i = 0; i < 5; i++) {

cxt.lineTo(Math.cos((18 + i * 72) * Math.PI / 180) * 50 + 100,

-Math.sin((18 + i * 72) * Math.PI / 180) * 50 + 100);

cxt.lineTo(Math.cos((54 + i * 72) * Math.PI / 180) * 25 + 100,

-Math.sin((54 + i * 72) * Math.PI / 180) * 25 + 100);

}

cxt.closePath();

cxt.stroke();

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-28所示。

分析

当然,对于多边形的绘制,我们可以将相应代码封装成一个个函数,以便在实际开发中直接调用。

2.5 实战题:绘制调色板

在使用绘图软件或取色软件的过程中,我们经常会见到各种调色板效果。常见的调色板有两种:方格调色板和渐变调色板。在这里,我们将使用这一章所学到的绘图方法来绘制这两种调色板。

举例:方格调色板

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id) {

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

for (var i = 0; i < 6; i++) {

for (var j = 0; j < 6; j++) {

cxt.fillStyle = "rgb(" + Math.floor(255 - 42.5 * i) + "," + Math. floor(255 - 42.5 * j) + ",0)";

cxt.fillRect(j * 25, i * 25, 25, 25);

}

}

}

</script>

</head>

<body>

<canvas id="canvas" width="200" height="200" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-29所示。

分析

对于这种方格调色板,实现的思路非常简单:我们可以使用两层for循环来绘制方格阵列,每个方格使用不同的颜色,其中变量i和j,用来为每一个方格产生唯一的RGB色彩值;我们仅修改其中的红色和绿色的值,而保持蓝色的值不变,就可以生成方格调色板。

接下来我们尝试绘制一个更加复杂的调色板——渐变调色板。

举例:渐变调色板

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title></title>

<script>

function $$(id) {

return document.getElementById(id);

}

window.onload = function () {

var cnv = $$("canvas");

var cxt = cnv.getContext("2d");

var r = 255, g = 0, b = 0;

for (i = 0; i < 150; i++) {

if (i < 25) {

g += 10;

} else if (i > 25 && i < 50) {

r -= 10;

} else if (i > 50 && i < 75) {

g -= 10;

b += 10;

} else if (i >= 75 && i < 100) {

r += 10;

} else {

b -= 10;

}

cxt.fillStyle = "rgb(" + r + "," + g + "," + b + ")";

cxt.fillRect(3 * i, 0, 3, cnv.height);

}

}

</script>

</head>

<body>

<canvas id="canvas" width="255" height="150" style="border:1px dashed gray;"></canvas>

</body>

</html>

预览效果如图2-30所示。

是不是很有趣呢?现在我们也可以开发一个属于自己的调色板了。

相关图书

HTML+CSS+JavaScript完全自学教程
HTML+CSS+JavaScript完全自学教程
零基础入门学习Web开发(HTML5 & CSS3)
零基础入门学习Web开发(HTML5 & CSS3)
HTML CSS JavaScript入门经典 第3版
HTML CSS JavaScript入门经典 第3版
HTML+CSS+JavaScript网页制作 从入门到精通
HTML+CSS+JavaScript网页制作 从入门到精通
从零开始:HTML5+CSS3快速入门教程
从零开始:HTML5+CSS3快速入门教程
从0到1 HTML5+CSS3修炼之道
从0到1 HTML5+CSS3修炼之道

相关文章

相关课程