参考:http://www.html5china.com/HTML5features/canvas/
开始:
- <canvas id="canvas" width="300" height="200">
- Fallback content, in case the browser does not support Canvas.
- canvas>
需要指明的是,由于无法保证所有用户使用的浏览器都能够支持 canvas 元素,所以在目前开发基于 canvas 的 Web 应用中需要增加“Fallback content”,以提示用户他们无法正常体验此功能的原因或建议他们去下载最新的浏览器。
这里,好奇的读者可能会问,既然这是一个普通的 DOM 节点,那么便意味着可以通过直接改变其 width 或 height 属性值来改变 canvas 的大小?确实如此,但是,正如之前提到的 canvas 是一种像素级别的绘图方法,因而,一旦动态调整 canvas 的大小,canvas 将被“重置”到一个新的初始状态,即便是如下这种操作,也会将 canvas 内的位图清除并将所有相关属性恢复到初始值的状态。当然,我们也可以把这当作重置 canvas 的小技巧来使用。
- document.getElementById("canvas").width = document.getElementById("canvas").width;
简单图形绘制
基于 canvas 的绘图并不是直接在 canvas 标记所创建的绘图画面上进行各种绘图操作,而是依赖画面所提供的 渲染上下文(Rendering Context),所有的绘图命令和属性都定义在渲染上下文当中。在通过 canvas id 获取相应的 DOM 对象之后首先要做的事情就是获取渲染上下文对象。 渲染上下文与 canvas 一一对应,无论对同一 canvas 对象调用几次 getContext() 方法,都将返回同一个上下文对象。目前,所有支持 canvas 标签的浏览器都支持 2D 渲染上下文,可以使用如下的代码来获取该对象。
var context = document.getElementById("canvas").getContext("2d");
除此之外,在不久的将来,开发人员还会能够得到基于 OpenGL 的 3D 渲染上下文以在 canvas 中进行 3D 绘图。
与 SVG 不同,canvas 原生支持的基本图形只有矩形一种,至于其他的圆形,多边形等图形则都由路径来负责绘制实现。清单 1 展示了如何使用渲染上下文中的矩形绘图方法完成了图 1 所示图形。
例子及说明:
清单 1. 绘制 canvas 矩形
|
绘制路径
在开始动手绘制路径之前,首先需要明确的是:矩形绘制 API 是一种即时性的 API,他会在相应的绘图函数执行完毕之后,将图形即时的渲染在画面上。然而路径绘制 API 并非如此,完整的路径绘制过程大致可以分为如下两个阶段:
- 定义路径轮廓:
在每个 canvas 实例对象中都拥有一个 path 对象,创建自定义图形的过程就是不断对 path 对象操作的过程。每当开始一次新的图形绘制任务,都需要先使用 beginPath() 方法来重置 path 对象至初始状态,进而通过一系列对 moveTo/lineTo 等画线方法的调用,绘制期望的路径,其中 moveTo(x, y) 方法设置绘图起始坐标,而 lineTo(x,y) 等画线方法可以从当前起点绘制直线,圆弧以及曲线到目标位置。最后一步,也是可选的步骤,是调用 closePath() 方法将自定义图形进行闭合,该方法将自动创建一条从当前坐标到起始坐标的直线。
- 绘制路径
定义完路径的轮廓,此时 canvas 画面中没有显示任何路径,开发人员还可以对路径进行修改。一旦确定完成,则需要继续调用 stroke()/fill() 函数来完成将路径渲染到画面的最后一步。路径的轮廓颜色和填充颜色由 strokeStyle 和 fillStyle 属性决定
- >
- <html>
- <head>
- <script type="text/javascript">
- window.onload=function test(){
- var canvas = document.getElementById('canvas');
- if (canvas.getContext){
- var ctx = canvas.getContext('2d'); // 获取 2D 渲染上下文
- ctx.clearRect(0,0,400,500) ;// 清除以(0,0)为左上坐标原点,300*200 矩形区域内所有像素
- ctx.fillStyle = '#00f'; // 设置矩形的填充属性,#00f 代表蓝色
- ctx.strokeStyle = '#f00'; // 设置矩形的线条颜色,#f00 代表红色
- ctx.fillRect(50,50,150,80); // 使用 fillStyle 填充一个 150*80 大小的矩形
- ctx.strokeRect(45,45, 160, 90); // 以 strokeStype 属性为边的颜色绘制一个无填充矩形
- }
- var canvas2 = document.getElementById('canvas2');
- if (canvas2.getContext){
- var ctx = canvas2.getContext('2d');
- ctx.fillStyle = '#00f';
- ctx.strokeStyle = '#f00';
- ctx.beginPath();
- ctx.arc(75,45,50,0,Math.PI, false); // 绘制一条半圆弧线
- ctx.closePath(); // 自动绘制一条直线来关闭弧线。若不调用此方法,将仅仅显示一条半圆弧
- ctx.fill(); // 可以尝试注释掉 fill 或者 stroke 函数,观察图形的变化
- ctx.stroke();
- }
- }
- script>
- head>
- <body>
- <canvas id="canvas" style="border:1px solid #c3c3c3;">
- Your browser does not support the canvas element.
- canvas>
- <canvas id="canvas2" style="border:1px solid #c3c3c3;">
- Your browser does not support the canvas element.
- canvas>
- body>
- html>
二维变形
Canvas 绘图中另一个重要的概念是 绘画状态(Drawing State),绘画状态反映了渲染上下文当前的瞬时状态,开发人员可以通过对绘画状态的保存 / 恢复操作而快速的回到之前使用的各种属性和变形操作。绘画状态主要由以下三个部分构成:
- 当前的变形矩阵(transformation matrix)
- 当前的裁剪区域(clipping region)
- 当前上下文中的属性,比如 strokeStyle, fillType, globalAlpha, font 等等。
需要指出的是,当前路径对象以及当前的位图都不包含在绘画状态之中,路径是持续性的对象,如前文所讲,只有通过 beginPath() 操作才会进行重置,而位图则是 canvas 的属性,并非属于渲染上下文的。
开发人员可以使用 save 和 restore 两种方法来保存和恢复 canvas 状态,每调用 save 方法,都会将当前状态压入堆栈中,而相应的 restore 方法则会从堆栈中弹出一个状态,并将当前画面恢复至该状态。绘画状态在 canvas 图形变形操作中应用极为广泛,也非常重要,因为调用一个 restore 方法远比手动恢复先前状态要简单许多,因而,一个较好的习惯是在做变形操作之前先保存 canvas 状态。
二维绘图的常用变形操作在 canvas 中都可到了很好的支持,包括平移(Translate),旋转(Rotate),伸缩(Scale)等等。由于所有的变形操作都基于变形矩阵,因而开发人员始终需要记住一点的就是,一旦没有使用 save/restore 操作保持住原来的绘图状态,那么后续的绘图操作,都会在当前所应用的变形状态下完成。清单 3 使用平移和旋转方法绘制了如下所示画面。
- >
- <html>
- <head>
- <script type="text/javascript">
- window.onload=function test(){
- var canvas = document.getElementById('canvas');
- if (canvas.getContext){
- var ctx = canvas.getContext('2d'); // 获取 2D 渲染上下文
- ctx.clearRect(0,0,400,500) ;// 清除以(0,0)为左上坐标原点,300*200 矩形区域内所有像素
- ctx.fillStyle = '#00f'; // 设置矩形的填充属性,#00f 代表蓝色
- ctx.strokeStyle = '#f00'; // 设置矩形的线条颜色,#f00 代表红色
- ctx.fillRect(50,50,150,80); // 使用 fillStyle 填充一个 150*80 大小的矩形
- ctx.strokeRect(45,45, 160, 90); // 以 strokeStype 属性为边的颜色绘制一个无填充矩形
- }
- var canvas2 = document.getElementById('canvas2');
- if (canvas2.getContext){
- var ctx = canvas2.getContext('2d');
- ctx.fillStyle = '#00f';
- ctx.strokeStyle = '#f00';
- ctx.beginPath();
- ctx.arc(75,45,50,0,Math.PI, false); // 绘制一条半圆弧线
- ctx.closePath(); // 自动绘制一条直线来关闭弧线。若不调用此方法,将仅仅显示一条半圆弧
- ctx.fill(); // 可以尝试注释掉 fill 或者 stroke 函数,观察图形的变化
- ctx.stroke();
- }
- var canvas3 = document.getElementById('canvas3');
- if (canvas3.getContext){
- var ctx = canvas3.getContext('2d');
- ctx.translate(150,80); // 将 canvas 的原点从 (0,0) 平移至(150,150)
- for (i=1;i<=2;i++){ // 绘制内外 2 层
- if ((i % 2) == 1) {ctx.fillStyle = '#00f';}
- else{ ctx.fillStyle = '#f00'; }
- ctx.save(); // 保持开始绘制每一层时的状态一致
- for (j=0;j<=i*6;j++){ // 每层生成点的数量
- ctx.rotate(Math.PI/(3*i)); // 绕当前原点将坐标系顺时针旋转 Math.Pi/(3*i) 度
- ctx.beginPath();
- ctx.arc(0,20*i,5,0,Math.PI*2,true);
- ctx.fill(); // 使用 fillType 值填充每个点
- }
- ctx.restore();
- }
- }
- }
- script>
- head>
- <body>
- <canvas id="canvas" style="border:1px solid #c3c3c3;">
- Your browser does not support the canvas element.
- canvas>
- <canvas id="canvas2" style="border:1px solid #c3c3c3;">
- Your browser does not support the canvas element.
- canvas>
- <canvas id="canvas3" style="border:1px solid #c3c3c3;">
- Your browser does not support the canvas element.
- canvas>
- body>
- html>