HTML5 是一个新兴标准,它正在以越来越快的速度替代久经考验的 HTML4。HTML5 是一个 W3C “工作草案” — 意味着它仍然处于开发阶段 — 它包含丰富的元素和属性,它们都支持现行的 HTML 4.01 版本规范。它还引入了几个新元素和属性,它们适用许多使用 web 页面的领域 — 音频、视频、图形、数据存储、内容呈现,等等。本文主要关注图形方面的增强:canvas。
新的 HTML5 canvas 是一个原生 HTML 绘图簿,用于 JavaScript 代码,不使用第三方工具。跨所有 web 浏览器的完整 HTML5 支持还没有完成,但在新兴的支持中,canvas 已经可以在几乎所有现代浏览器上良好运行了,但 Windows® Internet Explorer® 除外。幸运的是,一个解决方案已经出现,将 Internet Explorer 也包含进来。
本质上,canvas 元素是一个白板,直到您在它上面 “绘制” 一些可视内容。与拥有各种画笔的艺术家不同,您使用不同的方法在 canvas 上作画。您甚至可以在 canvas 上创建并操作动画,这不是使用画笔和油彩所能够实现的。
本 文探索新的 HTML canvas 元素,从简单地包含一个 canvas 元素到高级 JavaScript 交互(动画的关键)逐步进行演示。学习如何在一个 web 页面上显示 canvas。本文针对 web 设计师和开发人员,尽管 JavaScript 知识不是必须的,但理解该语言的运行方式将有所帮助。但是,HTML 知识是关键所在,尤其是如何创建一个基本 web 页面。
要查看本文展示的示例的实时实例,您需要一个浏览器并能访问 Internet。所有示例都在一个真实网站上提供(参见 参考资料)。
浏览器支持
确 定哪些浏览器支持 HTML5 和一个移动目标达到什么程度。在本文撰写之时,Google Chrome、Apple Safari 和 Mozilla Firefox 都支持大多数新的 HTML5 元素,它们都支持 canvas 元素。Internet Explorer 7 和 8 都不支持 HTML5;Internet Explorer 9 处于测试阶段,支持 HTML5,但还有一些问题。
在此期间,有一个针对不支持 HTML5 的 Internet Explorer 版本的补丁可用。这个补丁的前提是创建使用 JavaScript 代码的元素。例如,可以使用代码段 document.createElement('canvas')
创建一个可识别的 Canvas 标记;但是,这并不意味着有东西经过元素本身 。一个流行的解决方法是包含一个完整的基于 canvas 的 JavaScript 库,这个库由 Google 提供,称为 ExplorerCanvas— 或简称 excanvas
。下载并将其作为一个外部文件引用,如下所示。(参见 参考资料 中的链接,了解更多 excanvas
信息。)
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
通过包含 excanvas
,您向 Internet Explorer 提供 canvas 及其大多数方法。
创建您的第一个 canvas
由于 canvas 只是一个 HTML 标记,因此它的显示方式只是包含在标记中。第一个示例(如 图 1 所示)显示一个最简单的 canvas。它之所以可见,是因为它通过 style
属性获得了一个颜色方案,通过 width
和 height
属性获得了其大小。
图 1. 一个空白 canvas
这个页面的代码简短明了,如 清单 1 所示。
清单 1. 包含一个 canvas 的 web 页面的 HTML
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="400" height="400"
style="background-color:blue;border: 10px yellow solid"></canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
这个 canvas 的宽度和高度均为 400 像素,边框为黄色,背景为蓝色。canvas 上没有任何实际绘图;绘图通过属于 canvas 的 JavaScript 方法完成。
canvas 方法
表 1 列示了几个附加到 canvas 上下文的方法。
表 1. canvas 方法
方法 | 用途 |
| 公开在 canvas 上绘图需要的 API。惟一(当前)可用的 |
| 设置 canvas 的高度。默认值是 150 像素。 |
| 设置 canvas 的宽度。默认值是 300 像素。 |
| 创建一个线性渐变。起始坐标为 |
| 创建一个放射状渐变。圆圈的起始坐标是 |
| 向一个渐变添加一个颜色停止。颜色停止(color stop) 是渐变中颜色更改发生的位置。offset 必须介于 0 到 1 之间。 |
| 设置用于填充一个区域的颜色 — 例如, |
| 设置用于绘制一根直线的颜色 — 例如, |
| 填充一个定位于 |
| 绘制一个定位于 |
| 将绘图位置移动到坐标 |
| 从绘图方法结束的最后位置到 |
构建更复杂的 canvas 应用程序
本小节将展示一系列示例,每个示例的功能都比前一个示例略有增加。
更深刻的视觉体验
首先,将一组矩形放置到 canvas 上。记住,矩形是拥有 4 条直边和 4 个直角的图形,正方形是矩形的变体。图 2 显示 canvas 上有一系列矩形,每个矩形都比前一个略小。注意,每个矩形的颜色都不同,使其更清晰明确。
图 2. 使用一些矩形填充的 canvas
清单 2 显示了用于创建图 2 中的 canvas 的代码。每个矩形都由两行代码创建:首先,fillStyle
方法使用颜色定义的红、绿、蓝(RGB)格式定义颜色(fillStyle='rgb(255,0,0)
)。然后,fillRect
方法(fillRect(50,50,300,300)
)定义大小。前两个值设置起始坐标,后两个值设置结束坐标。
清单 2. 使用 JavaScript 代码创建上下文并使用各种方法
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
<script>
window.οnlοad=function() {
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
mycontext.fillStyle='rgb(0,0,255)';
mycontext.fillRect(0,0,400,400);
mycontext.fillStyle='rgb(255,0,0)';
mycontext.fillRect(50,50,300,300);
mycontext.fillStyle='rgb(0,255,0)';
mycontext.fillRect(100,100,200,200);
mycontext.fillStyle='rgb(100,100,100)';
mycontext.fillRect(125,175,150,25);
}
</script>
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="400" height="400" style="border: 10px yellow solid">
</canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
要在 canvas 上绘图,通过将 getContext('2d')
应用到 canvas 元素访问提供方法的 API。通过这个 document.getElementById
方法,canvas 元素被设置为一个 JavaScript 变量:
var mycanvas=document.getElementById("myCanvasTag");
然后将 getContext
应用到 canvas 元素,如下所示。
var mycontext=mycanvas.getContext('2d');
一旦一个变量被设置到上下文,所有方法就可以使用了。
下一个示例展示如何结合两种技术。一种是矩形重叠,方法是使用 fillRect
参数来定位矩形(见 图 3)。
图 3. 向一个 canvas 上的矩形应用透明度
第二种技术是 RGB 颜色处理的变体,即添加透明度。不使用 rgb
,而是使用 rgba
。a
表示 alpha 通道,该通道控制透明度。在图 3 中的示例中,第二个矩形的透明度被设置为 50%(或 .5),第三个设置为 25%(或 .25)。清单 3 显示了完整的标记。
清单 3. 使用透明度
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
<script>
window.οnlοad=function() {
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
mycontext.fillStyle='rgb(0,0,255)';
mycontext.fillRect(30,30,300,300);
mycontext.fillStyle='rgba(0,255,0,0.5)';
mycontext.fillRect(60,60,300,300);
mycontext.fillStyle='rgba(255,0,0,0.25)';
mycontext.fillRect(90,90,300,300);
}
</script>
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="400" height="400" style="border: 10px yellow solid">
</canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
渐变— 经过协调的颜色混合 — 原生于 canvas ,通过两种方法:createLinearGradient
和 createRadialGradient
。图 4 展示了一个线性渐变。addColorStop
方法定义一个颜色,以及它在渐变中变为活动状态的位置。由于一个渐变可以拥有多个颜色停止,因此这种定位是主观的。颜色定位值必须介于 0 到 1 之间,但测试变体和颜色停止的数量可以生成不同的结果,即使一个值(比如 .25)保持不变。换句话说,一个颜色停止可以将其位置设定为 .25,但是相关颜色可以从整个渐变路径的四分之一处之后一点开始发生,一直持续到渐变结束,具体情况取决于您设置其他颜色停止的位置。记住,这是一个新 的实现,可能还在改进过程中。渐变的一个好处是它们总是引人注目,无论代码和结果是否经过完美的协调。
图 4. 一个线性渐变
图 4 中的渐变通过 清单 4 中的 JavaScript 代码创建。
清单 4. 创建一个线性渐变
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
var mygradient=mycontext.createLinearGradient(30,30,300,300);
mygradient.addColorStop(0,"#FF0000");
mygradient.addColorStop(1,"#00FF00");
mycontext.fillStyle=mygradient;
mycontext.fillRect(0,0,400,400);
注意,清单 4 中的颜色停止被全面实现为从这个方法本身创建的一个实时(on-the-fly)渐变的一个方法。语句 mygradient.addColorStop(0,"#FF0000")
显示颜色停止拥有两个参数:位置和颜色。
图 5 展示了一个放射状渐变。用于创建这个渐变的代码与清单 4 中的代码类似,除了使用 createRadialGradient
方法替代 createLinearGradient
方法之外。
图 5. 一个放射状渐变
用于创建图 5 中的放射状渐变的代码如 清单 5 所示。注意所有 5 个颜色停止。
清单 5. 创建一个放射状渐变
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
<script>
window.οnlοad=function() {
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
var mygradient=mycontext.createRadialGradient(300,300,0,300,300,300);
mygradient.addColorStop("0","magenta");
mygradient.addColorStop(".25","blue");
mygradient.addColorStop(".50","green");
mygradient.addColorStop(".75","yellow");
mygradient.addColorStop("1.0","red");
mycontext.fillStyle=mygradient;
mycontext.fillRect(0,0,400,400);
}
</script>
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="400" height="400" style="border: 10px blue solid">
</canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
多个 canvas
一个 web 页面能够包含多个 canvas,每个 canvas 引用它们自己的独特 JavaScript 上下文变量。结果,每个 canvas 都独立于其他 canvas 工作。图 6 展示了 4 个 canvas,每个 canvas 上的图像都不同。
图 6. 一个 web 页面上的多个 canvas
清单 6 显示了用于创建图 6 中的页面的代码。注意,每个 canvas 都有一个惟一 ID 且每个上下文都是惟一的。
清单 6. 一个 web 页面上的多个 canvas
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
<script>
window.οnlοad=function() {
var mycontext1=document.getElementById("myCanvasTag1").getContext('2d');
var mycontext2=document.getElementById("myCanvasTag2").getContext('2d');
var mycontext3=document.getElementById("myCanvasTag3").getContext('2d');
var mycontext4=document.getElementById("myCanvasTag4").getContext('2d');
// gradient 1
var mygradient1=mycontext1.createLinearGradient(30,30,90,90);
mygradient1.addColorStop(0,"#FF0000");
mygradient1.addColorStop(1,"#00FF00");
mycontext1.fillStyle=mygradient1;
mycontext1.fillRect(0,0,100,100);
// gradient 2
var mygradient2=mycontext2.createLinearGradient(30,30,90,90);
mygradient2.addColorStop(1,"#FF0000");
mygradient2.addColorStop(0,"#00FF00");
mycontext2.fillStyle=mygradient2;
mycontext2.fillRect(0,0,100,100);
var mygradient3=mycontext3.createLinearGradient(30,30,90,90);
mygradient3.addColorStop(0,"#0000FF");
mygradient3.addColorStop(.5,"#00FFDD");
mycontext3.fillStyle=mygradient3;
mycontext3.fillRect(0,0,100,100);
var mygradient4=mycontext1.createLinearGradient(30,30,90,90);
mygradient4.addColorStop(0,"#DD33CC");
mygradient4.addColorStop(1,"#EEEEEE");
mycontext4.fillStyle=mygradient4;
mycontext4.fillRect(0,0,100,100);
}
</script>
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag1" width="100" height="100" style="border: 10px blue solid">
</canvas>
<canvas id="myCanvasTag2" width="100" height="100" style="border: 10px green solid">
</canvas>
<br />
<canvas id="myCanvasTag3" width="100" height="100" style="border: 10px red solid">
</canvas>
<canvas id="myCanvasTag4" width="100" height="100" style="border: 10px black solid">
</canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
JavaScript 事件和动画
本 文已经展示了可用于 canvas 的各种方法,每种方法都创建了一个可视结果。现在我们提高一个等级,看看 canvas 如何实现事件和动画。JavaScript 能够识别许多事件,包括在一个特定 web 页面元素上方移动或悬停鼠标。JavaScript 语言能够识别更多事件,下面的示例将使用其中几个。
整合事件
图 7 中的示例是使用前面清单中的方法创建的。现在我们添加几个新技术。面部的鼻子、眼睛和圆形项目以及外部边界都使用 arc
方法创建。眼睫毛被绘制为线条,嘴被创建为一条贝赛尔曲线。图 7 还在 canvas 底部显示了一些文本,这是使用 fillText
方法创建的。
图 7. 使用 JavaScript 事件绘制一张正在眨眼的脸
清单 7 显示图 7 使用的代码。
清单 7. 使用事件创建一个眨眼
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
<script>
window.οnlοad=function() {
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
//draw face
mycontext.beginPath();
mycontext.arc(300, 250, 200, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.stroke();
//draw left eye
mycontext.beginPath();
mycontext.arc(220, 150, 30, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.fillStyle='rgb(100,100,225)';
mycontext.fill();
//draw left iris
mycontext.beginPath();
mycontext.arc(220, 150, 10, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.fillStyle='rgb(0,0,0)';
mycontext.fill();
//draw left eyelid
mycontext.beginPath();
mycontext.arc(220, 150, 30, 0, Math.PI, true);
mycontext.closePath();
mycontext.fillStyle='rgb(200,200,200)';
mycontext.fill();
//draw left eyelashes
mycontext.strokeStyle='rgb(0,0,0)';
lashes(mycontext,198, 170, 193, 185);
lashes(mycontext,208, 177, 204, 193);
lashes(mycontext,220, 180, 220, 195);
lashes(mycontext,232, 177, 236, 193);
lashes(mycontext,242, 170, 247, 185);
mycontext.stroke();
openeye();
//draw right eyelashes
mycontext.strokeStyle='rgb(0,0,0)';
lashes(mycontext, 358, 170, 353, 185);
lashes(mycontext, 368, 177, 364, 193);
lashes(mycontext, 380, 180, 380, 195);
lashes(mycontext, 392, 177, 396, 193);
lashes(mycontext, 402, 170, 407, 185);
mycontext.stroke();
//draw nose
mycontext.beginPath();
mycontext.arc(300, 250, 20, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.stroke();
// draw smile
mycontext.beginPath();
mycontext.lineWidth = 10;
mycontext.moveTo(180, 320);
mycontext.bezierCurveTo(140, 320, 340, 420, 400, 360);
mycontext.closePath();
mycontext.stroke();
//draw message at bottom
mycontext.font="1em sans-serif";
mycontext.fillStyle="rgb(0,0,0)";
mycontext.fillText("Move the mouse over and off the canvas - the face winks!", 10, 480);
}
function lashes(cntx,x1,y1,x2,y2) {
cntx.moveTo(x1,y1);
cntx.lineTo(x2,y2);
}
function closeeye() {
//close right eye
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
mycontext.beginPath();
mycontext.arc(380, 150, 30, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.fillStyle='rgb(200,200,200)';
mycontext.fill();
}
function openeye() {
//open right eye
var mycanvas=document.getElementById("myCanvasTag");
var mycontext=mycanvas.getContext('2d');
mycontext.beginPath();
mycontext.arc(380, 150, 30, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.fillStyle='rgb(100,100,225)';
mycontext.fill();
//draw right iris
mycontext.beginPath();
mycontext.arc(380, 150, 10, 0, Math.PI * 2, true);
mycontext.closePath();
mycontext.fillStyle='rgb(0,0,0)';
mycontext.fill();
//draw right eyelid
mycontext.beginPath();
mycontext.arc(380, 150, 30, 0, Math.PI, true);
mycontext.closePath();
mycontext.fillStyle='rgb(200,200,200)';
mycontext.fill();
}
</script>
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="600" height="500" style="border: 5px blue solid"
οnmοuseοver="closeeye()" οnmοuseοut="openeye()"></canvas>
<br /><br />
<a href="index.html">back</a>
</div>
</body>
</html>
图 7 中的脸通过一些 JavaScript 事件而改变。特别是, onmouseover
和 onmouseout
事件分别用于调用 closeeye()
和 openeye()
函数。这些函数不是 canvas 的方法,但是标准 JavaScript 函数。事件和函数之间的连接在 canvas 元素本身中进行。在 清单 7 中,页面的主体区域接近代码的底部,那是 canvas 所在的位置。canvas 标记内是:
οnmοuseοver="closeeye()" οnmοuseοut="openeye()"
清单 7 中出现了一个新的构造 —beginPath()
和 endPath()
的使用,它们用于明确区分独立的复杂绘图动作。封装在其中的代码绘制一个特殊的图像,以分隔其他绘图动作。
关于 清单 7 中的代码的几个值得注意的地方列示如下:
- 当页面打开时,通过调用
openeye()
函数来绘制右眼。 - 使用
fillText
方法将文本写到 canvas 上。 - 在
arc
方法中,MATH.PI * 2
创建了一个完整的圆圈,而MATH.PI
将只创建一个半圆(例如,眼皮)。
动画
JavaScript 打包了一个强大的编程利器。这种语言能够执行很多操控,如 清单 8 所示。这个代码重复运行,在 canvas 上绘制一些线条。线条颜色随机设置。
清单 8. 使用 JavaScript 创建动画
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Canvas Demo</title>
<!--[if IE]>
<script type="text/javascript" src="excanvas.js"></script>
<![endif]-->
</head>
<body>
<div style="margin-left:30px;">
<canvas id="myCanvasTag" width="400" height="400" style="border: 10px blue solid">
</canvas>
<br /><br />
<a href="index.html">back</a>
</div>
<script>
var mycanvas = document.getElementById("myCanvasTag")
var mycontext = mycanvas.getContext('2d');
var x;
var y;
var x2;
var y2;
var r;
var g;
var b;
function line() {
x=Math.floor(Math.random()*190) + Math.floor(Math.random()*190);
y=Math.floor(Math.random()*190) + Math.floor(Math.random()*190);
x2=Math.floor(Math.random()*190) + Math.floor(Math.random()*190);
y2=Math.floor(Math.random()*190) + Math.floor(Math.random()*190);
r=Math.floor(Math.random()*255);
g=Math.floor(Math.random()*255);
b=Math.floor(Math.random()*255);
mycontext.moveTo(x, y);
mycontext.lineTo(x2, y2);
mycontext.strokeStyle='rgb(' + r + ',' + g + ',' + b + ')';
mycontext.lineWidth=Math.floor(Math.random()*6);
mycontext.stroke();
mycontext.restore();
}
setInterval(line, 100);
</script>
</body>
</html>
图 8 显示了这个动画的一张快照。清单 8 中的代码与本文其他所有代码示例都不同,因为 JavaScript 块被放置到页面底部,canvas 元素下方。这确保 canvas 在代码运行之前就已经被呈现了。
图 8. JavaScript 用于绘制无穷无尽的随机线条
结束语
HTML5 被定位于用于改变 web 开发的面貌。新的元素使得页面布局更简单,支持通过浏览器存储本地数据,拥有 canvas 之类的音频、视频和图形平台。随着浏览器升级以支持更多新功能,web 的性质和用户体验将变得妙趣横生。web 开发前景一片光明!
参考资料
学习
- 找到本文中的示例的 实时演示 。
- WHATWG 是一个开发人员社区,协助 W3C 改进 HTML5。
- 马上 开始实现 HTML5。
- 阅读来自 Mozilla 开发人员的 canvas 教程和演示。
- PHPGuru.org 提供关于 canvas 用法的信息,以及许多很棒的演示和示例。
- developerWorks Web development 专区:通过专门关于 Web 技术的文章和教程,扩展您在网站开发方面的技能。
- developerWorks Ajax 资源中心:这是有关 Ajax 编程模型信息的一站式中心,包括很多文档、教程、论坛、blog、wiki 和新闻。任何 Ajax 的新信息都能在这里找到。
- developerWorks Web 2.0 资源中心,这是有关 Web 2.0 相关信息的一站式中心,包括大量 Web 2.0 技术文章、教程、下载和相关技术资源。您还可以通过 Web 2.0 新手入门 栏目,迅速了解 Web 2.0 的相关概念。
- 随时关注 developerWorks 技术活动和网络广播。
- 观看 developerWorks 演示中心,包括面向初学者的产品安装和设置演示,以及为经验丰富的开发人员提供的高级功能。
- 查看 HTML5 专题,了解更多和 HTML5 相关的知识和动向。
获得产品和技术
- 下载 用于 Internet Explorer 的 excanvas.js 库。
- 下载 IBM 产品评估试用版软件 或 IBM SOA 人员沙箱,并开始使用来自 DB2®、Lotus®、Rational®、Tivoli® 和 WebSphere® 的应用程序开发工具和中间件产品。
标签:canvas,Math,fillStyle,HTML5,var,绘制,mycontext From: https://blog.51cto.com/u_8895844/6293334