- 简介
- 历史
- 历史(续)
- 历史(续二)
- 历史(续三)
- 检测 HTML5 特性
- 检测 HTML5 特性(续)
- 检测 HTML5 特性(续二)
- 检测 HTML5 特性(续三)
- 它的含义是什么?
- 它的含义是什么?(续)
- 它的含义是什么?(续二)
- 它的含义是什么?(续三)
- 它的含义是什么?(续四)
- 它的含义是什么?(续五)
- 绘图
- 绘图(续)
- 绘图(续二)
- 绘图(续三)
- 绘图(续四)
- 绘图(续五)
- Web 视频
- Web 视频(续)
- Web 视频(续二)
- Web 视频(续三)
- Web 视频(续四)
- 地理位置
- 地理位置(续)
- 本地存储
- 本地存储(续)
- 离线 Web 程序
- 离线 Web 程序(续)
- 表单
- 表单(续)
- 表单(续二)
- 可扩展性
- 可扩展性(续)
- 可扩展性(续二)
- 可扩展性(续三)
- 可扩展性(续四)
- 历史 API
绘图(续四)
图像
IE | Firefox | Safari | Chrome | Opera | iPhone | Android |
7.0+* | 3.0+ | 3.0+ | 3.0+ | 10.0+ | 1.0+ | 1.0+ |
* IE 7.0 和 8.0 需要使用第三方 JS 库 explorercanvas ;IE9 原生支持。 |
这里是一只猫的图片:
上面的图像是放在 <img>
里面的。下面则是一只看上去一样的猫,不过它是使用 <canvas>
绘制的:
画布的绘图上下文有一个 drawImage()
方法,用于在画布上绘制图像。这个方法有 3 个重载,分别接受 3、5、9 个参数。
drawImage(image, dx, dy)
接受一幅图像,并且将其绘制到画布上。给定 (dx, dy) 是该图像左上角的坐标。坐标 (0, 0) 意味着图像出现在画布左上角。drawImage(image, dx, dy, dw, dh)
接受一幅图像,将其缩放至宽度为 dw,高度为 dh 后,在将其绘制到画布坐标 (dx, dy) 位置。drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh)
接受一幅图像,然后将其按照矩形 (sx, sy, sw, sh) 进行裁剪,再缩放至大小为 (dw, dh),最后将其绘制到画布坐标 (dx, dy) 位置。
HTML5 标准 这样 解释 drawImage()
的参数:
源矩形是一个矩形[位于原始图像],其四个顶点的坐标分别为 (sx, sy),(sx+sw, sy),(sx+sw, sy+sh) 和 (sx, sy+sh)。
目标矩形是一个矩形[位于画布内],其四个顶点的坐标分别为 (dx, dy),(dx+dw, dy),(dx+dw, dy+dh) 和 (dx, dy+dh)。
为了在画布上绘制图像,我们首先需要一副图像。图像可以是已存在的 <img> 元素,也可以使使用 JavaScript 创建的 Image()
对象。无论如何,你需要确保该图像在绘制到画布之前已经被加载完全。
如果你使用已有的 <img>
元素,你可以放心地把绘制代码放到 window.onload 事件回调里面:
<img id="cat" src="images/cat.png" alt="sleeping cat" width="177" height="113"> <canvas id="e" width="177" height="113"></canvas> <script> window.onload = function() { var canvas = document.getElementById("e"); var context = canvas.getContext("2d"); var cat = document.getElementById("cat"); context.drawImage(cat, 0, 0); }; </script>
如果你完全使用 JavaScript 创建图像对象,你应该把绘制的代码放到 Image.onload 事件中去:
<canvas id="e" width="177" height="113"></canvas> <script> var canvas = document.getElementById("e"); var context = canvas.getContext("2d"); var cat = new Image(); cat.src = "images/cat.png"; cat.onload = function() { context.drawImage(cat, 0, 0); }; </script>
传递给 drawImage()
方法可选的第三和第四个参数用于控制图像的缩放。下面给出的是同一副图像,将其大小缩至一半,然后在一个画布上的不同坐标进行重复绘制的效果:
cat.onload = function() { for (var x = 0, y = 0; x < 500 && y < 375; x += 50, y += 37) { context.drawImage(cat, x, y, 88, 56); } };
不过,到现在为止,我们可能还会有一个问题要问:为什么你要在 canvas 上绘制图像?为什么要编写那么复杂的代码,而不直接用 <img>
加上一些 CSS 规则实现?就像上面说的“复杂”的效果,也不过是添加 10 个 <img>
就可以了。
简单的回答是,同你希望在画布上画出文本的原因是一致的。画布的坐标图包括了文本、直线和特殊形状。所谓画布上的文本不过是一项复杂工程中的一小部分。一个更加复杂的图标可以很简单地使用 drawImage()
来添加诸如图标、精灵或者其他图像元素。
IE 怎么办?
Internet Explorer 9.0 之前的版本都不支持 canvas API(IE9 是完全支持 canvas API 的)。但是,老版本的 Internet Explorer 是支持 Microsoft 的专有技术 VML 的。这种技术在很大程度上很像 <canvas>
元素。因此,我们有了 excanvas.js。
Explorercanvas (excanvas.js) 是一个基于 Apache 协议开源的 JavaScript 库,在老版本的 Internet Explorer 上实现了 canvas API。为使用这个库,我们需要在页面的顶部加上 <script>
元素。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Dive Into HTML5</title> <!--[if lt IE 9]> <script src="excanvas.js"></script> <![endif]--> </head> <body> ... </body> </html>
<!--[if lt IE 9]>
和 <![endif]-->
就是我们前面提到的条件注释。Internet Explorer 将按照 if 语句解释它们:“如果当前浏览器版本低于 9,则执行这个块。”而其他所有浏览器都会将其解释为普通的 HTML 注释。最终的结果是,Internet Explorer 7 和 8 将下载 excanvas.js 脚本并执行,而其他浏览器则会连同脚本一起忽略(不下载、不执行,什么都不做)。这将会使支持 canvas API 的浏览器能够更快地加载你的页面。
一旦你在你的页面的 <head>
中引入了 excanvas.js,你就不需要为 Internet Explorer 做任何额外的操作了。只需要添加 <canvas>
标记,或者使用 JavaScript 动态创建。接下来的指令和我们前面说的一样,获取 <canvas>
的绘图上下文,然后绘制形状、文本或者填充图像。
好吧…其实也有一些区别,主要是有下面一些限制:
- 只有线性渐变,不支持辐射渐变;
- 填充图像必须向两侧重复;
- 不支持裁剪区域;
- 不是同一的缩放,可能造成边框笔触缩放不正确。
它很慢。我们不应该使用这种技术去实现一些惊人的动作,因为原本 Internet Explorer 的 JavaScript 解析器就比其他浏览器蛮很多。一旦你使用 JavaScript 库开始绘制复杂的形状,这个库会将这些指令转换成完全不同的另外的技术实现,效率由此降低很多。简单的例子,比如绘制几条直线或者图像变换,不会看出来,但是如果你开始使用基于 canvas 的动画或者其他疯狂的举措,性能下降一眼就看出来了。
使用 excanvas.js 还有一个警告,这个问题是我使用这个库创建本章的这些例子是遇到的,ExplorerCanvas 会在你包含了 excanvas.js 的页面中自动初始化它自己的假的 canvas。但是这并不意味着 Internet Explorer 能够立刻使用它。在特定的情形下,你可以在这个假的 canvas 差不多完成的时候给出一个竞争条件。主要问题是在你使用 <canvas>
做任何操作,比如获取绘图上下文的时候,Internet Explorer 会抱怨说“该对象不支持这个属性或者方法”。
最简单的解决方案是将所有 canvas 相关的代码放到 onload
事件触发之后。这可能会耽误一段时间,特别是你的页面包含了很多图像或者视频的时候,它们都会推迟 onload
事件,但至少这样做能够让 ExplorerCanvas 正确的运行起来。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论