HTML5添加的最受欢迎的功能就是<canvas>元素,这个元素负责在页面中设定一个区域,然后就可以通过JavaScript动态在这个区域绘制图形。

主流浏览器都支持canvas,如IE9+、FireFox1.5+、Safari2+、Opera9+、Chrome、iOS版Safari及安卓版Webkit,IE8及之前的版本不支持<canvas>元素。

Canvas除了具备基本绘图能力的2D上下文,还有一个名为WebGL的3D上下文。目前支持canvas元素的浏览器都支持2D上下文,但对WebGL的支持还不够好。

 

1、基本用法

要使用<canvas>元素,就要先设置width和height属性,指定可以绘制的区域大小,<canvas>和</canvas>标签中的内容是当浏览器不支持<canvas>元素时显示的信息。

注意1:为了避免绘图时canvas元素还未加载,建议将绘制脚本放置在</body>标签之前。

注意2:canvas元素默认宽 300px,高 150px,设置canvas元素的width和height属性有几种方法:

1) HTML中:<canvas width="500" height="500">浏览器不支持canvas元素</canvas>(推荐使用)

2)JavaScript中:canvas.width = 500; canvas.height = 500; (可以使用)

3) CSS中:canvas{ width:500px; height:500px; }(会拉伸,不建议使用)。

4) HTML中:<canvas style="width:500px;height:500px">浏览器不支持canvas元素</canvas>(会拉伸,不建议使用)。

5) JavaScript中:canvas.style.width = "500px"; canvas.style.height = "500px"; (会拉伸,不建议使用)。

6) jQuery中:$("canvas").width(500);$("canvas").height(500); (会拉伸,不建议使用)。

要在画布canvas上绘图,需要取得绘图上下文。要取得绘图上下文的引用,需要调用getContext()方法并传入上下文的名字,如传入“2d”,就可以取得2D上下文对象。在使用<canvas>元素之前,需要先检测getContext()方法是否存在。

使用toDataURL()方法,可以导出在<canvas>元素上绘制的图像,该方法接受一个参数,即图像的MIME类型格式,而且适合用于创建图像的任何上下文。

取得画布中的一幅PNG格式的图像(默认情况下,浏览器会将图像编码为PNG格式,除非另行指定,Firefox和Opera也支持基于image/jpeg的JPEG编码格式,由于该方法是后来才增加的,所以支持canvas的浏览器也是在较新的版本中才加入了对它的支持,如IE9+、Firefox3.5和Opera10):

var canvas = document.getElementsByTagName("canvas")[0];
if (canvas.getContext) {
	var imgURI = canvas.toDataURL("image/png");
	var image = document.createElement("img");
	image.src = imgURI;
	document.body.appendChild(image);
}


2、2D上下文

使用2D绘图上下文提供的方法,可以绘制简单的2D图形,如矩形、弧线和路径。

2D上下文的坐标开始于<canvas>元素的左上角,原点坐标是(0, 0),所有坐标值都基于原点进行计算,默认情况下,width和height表示水平和垂直两个方向上可用的像素数目。

1) 填充和描边

填充:用指定的样式(颜色、渐变或图像)填充图形。

描边:只在图形的边缘画线。

大多数2D上下文都会细分为填充和描边两个操作,而操作的结果取决于两个属性:fillStyle和strokeStyle,这两个属性的值可以是字符串、渐变对象或模式对象,默认值都是“#000000”。如果为它们指定表示颜色的字符串,可以使用CSS中指定颜色的任何形式,包括颜色名、十六进制码、rgb、rgba、hsl或hsla。

 

2) 绘制矩形

矩形是唯一一种可以直接在2D上下文中绘制的形状。与矩形有关的方法包括:fillRect()、strokeRect()和clearRect(),这三个方法都能接收4个参数:矩形的x坐标、矩形的y坐标、矩形宽度和矩形高度,单位都是像素。

fillRect()方法在画布上绘制的矩形会填充指定的颜色,填充的颜色通过fillStyle属性指定。

strokeRect()方法在画布上绘制的矩形会使用指定的颜色描边,描边的颜色通过strokeStyle属性指定。

clearRect()方法用于清除画布上的矩形区域,本质上,该方法可以吧绘制上下文中的某个矩形区域变透明。通过绘制形状然后再清除指定区域,可以生成切掉一块的效果。

var canvas = document.getElementsByTagName("canvas")[0];
if (canvas.getContext) {
	var context = canvas.getContext("2d");
	context.fillStyle = "red";
	context.fillRect(10, 10, 50, 50);
	context.strokeStyle= "blue";
	context.strokeRect(30, 30, 50, 50);
	context.clearRect(40, 40, 10, 10); // 在两个矩形重叠的地方清除一个小矩形
}


3) 绘制路径

通过路径可以创造出复杂的形状和线条。

绘制新路径的步骤如下:

① 调用beginPath()方法,表示要开始绘制新路径。

② 调用下列方法来绘制路径:

a. arc(x, y, radius, startAngle, endAngle, counterClockwise):以(x, y)为圆心,绘制一条弧线,半径为radius,起始和结束角度分别为startAngle和endAngle,counterClockwise为true表示逆时针计算,为false表示顺时针计算;

b. arcTo(x1, y1, x2, y2, radius):利用上一点、点(x1, y1)和点(x2, y2)这三个点所形成的夹角,绘制一段与夹角的两边相切并且半径为radius的圆上的弧线。夹角的一边是上一点与(x1, y1)的连线,另一边是(x1, y1)(x2, y2)的连线,弧线的起点就是上一点所在边与圆的切点,弧线的终点就是点(x2,y2)所在边与圆的切点,并且绘制的弧线是两个切点之间长度最短的那个圆弧。此外,如果上一点不是弧线起点,arcTo()方法还将添加一条当前端点到弧线起点的线段

c. bezierCurveTo(c1x, c1y, c2x, c2y, x, y):从上一点开始绘制一条曲线,到(x, y)为止,并且以(c1x, c1y)和(c2x, c2y)为控制点。

d. lineTo(x, y):从上一点开始绘制一条直线,到(x, y)为止。

e. moveTo(x, y):将绘图游标移动到(x, y),不画线。

f. quadraticCurveTo(cx, cy, x, y):从上一点开始绘制一条二次曲线,到(x, y)为止,并且以(cx, cy)作为控制点。

g. rect(x, y, width, height):从点(x, y)开始绘制一个矩形,宽度和高度分别为width和height,该方法绘制的是矩形路径,而不是fillRect()和strokeRect()所绘制的独立的形状。

③ 创建了路径后,有以下几种选择:

a. 若想绘制一条连接路径起点的线条,可以调用closePath();

b. 若路径已经完成,可以调用fill()方法填充路径,使用的是fillStyle;

说明:fill()方法用于填充路径,fillRect()方法用于填充矩形,rect()与fill()方法合用相当于fillRect()。也就是说,绘制填充矩形有两种方法,但绘制填充圆形只能通过arc()与fill()方法合用。

c. 若路径已经完成,还可以调用stroke()方法对路径描边,使用的是strokeStyle;

说明:stroke()方法用于路径描边,strokeRect()方法用于填充矩形,rect()与stroke()方法合用相当于strokeRect()。也就是说,绘制描边矩形有两种方法,但绘制描边圆形只能通过arc()与stroke()方法合用。

注意:moveTo()和lineTo只是定义了路径,还需要stroke()方法才会实际绘制出路径。在beginPath()和Stroke()或closePath()之间若有多次设置lineWidth或strokeStyle,则后面设置的值会覆盖前面设置的值,若想要对两条路径设置不同的lineWidth或strokeStyle,需要为第一条路径设置lineWidth或strokeStyle通过Stroke()或closePath()结束第一条路径,再通过beginPath开始第二条路径后设置第二条路径的lineWidth或strokeStyle。

var canvas = document.getElementsByTagName("canvas")[0];  
if (canvas.getContext) {  
	var context = canvas.getContext("2d");  
	// 开始路径
	context.beginPath();
	// 绘制外圆
	context.arc(100, 100, 99, 0, 2 * Math.PI, false);
	// 绘制内圆
	context.moveTo(194, 100);
	context.arc(100, 100, 94, 0, 2 * Math.PI, false);
	// 绘制分针
	context.moveTo(100, 100);
	context.lineTo(100, 15);
	// 绘制时针
	context.moveTo(100, 100);
	context.lineTo(35,100);
	// 描边路径
	context.stroke();
} 

注意:在绘制内圆之前,必须把路径移到内圆上的某一点,以避免绘制出多余的线条。

d. 最后还可以调用clip(),在路径上创建一个剪切区域。

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style>
    </style>
</head>
<body>
	<br>没有clip():<br>
	<canvas id="canvas1" width="400" height="200" style="border:1px solid grey">浏览器不支持canvas元素</canvas>
	<br>有clip():<br>
	<canvas id="canvas2" width="400" height="200" style="border:1px solid grey">浏览器不支持canvas元素</canvas>
	<script src="js/jquery-1.8.2.min.js"></script>
    <script>
		var canvas1 = document.getElementById("canvas1");
		var context1 = canvas1.getContext("2d");
		context1.rect(50, 50, 200, 100);
		context1.stroke();
		context1.fillStyle = "red";
		context1.fillRect(0, 0, 150, 100);
		var canvas2 = document.getElementById("canvas2");
		var context2 = canvas2.getContext("2d");
		context2.rect(50, 50, 200, 100);
		context2.stroke();
		context2.clip();
		context2.fillStyle="red";
		context2.fillRect(0, 0, 150, 100);
    </script>
</body>
</html> 

在2D绘制上下文中,路径是一种主要的绘图方式,因为路径能为要绘制的图形提供更多控制。isPointInPath()方法接收x和y坐标作为参数,用于在路径被关闭之前确定画布上的某一点是否位于路径上。

if (context.isPointInPath(100, 100))
	alert("Point (100, 100) is in the path");


4) 绘制文本

绘制文本主要有两个方法:fillText()和strokeText(),这两个方法可以接收4个参数,要绘制的文本字符串,x坐标,y坐标和可选的最大像素宽度(该可选参数尚未得到所有浏览器支持,提供该参数后,调用fillText()或strokeText()时若传入的字符串大于最大宽度,则绘制的文本字符的高度正确,,但宽度会收缩以适应最大宽度),fillText()方法使用fillStyle属性绘制文本,strokeText()方法使用strokeStyle属性绘制文本,且这两个方法都以下列3个属性为基础:

① font:表示文本样式、大小和字体,用CSS指定字体的格式来指定;

② textAlign:表示文本对齐方式,可能的值有start,end,left,right,center,建议使用start,end,不要使用left和right,前两者适用于从左到右和从右到左显示的语言。start表示x坐标的位置是文本左端的位置(从左到右阅读的语言),end表示x坐标的位置是文本右端的位置(从右到左阅读的语言);

③ textBaseline:表示文本的基线,可能的值有top,hanging,middle,alphabetic,ideographic和bottom,top表示y坐标的位置是文本顶端的位置,bottom表示y坐标的位置是文本底端的位置,hanging,alphabetic,ideographi表示y坐标分别指向字体的特定基线坐标。

这几个属性都有默认值,因此没有必要每次使用它们都重新设置一次值。

var canvas = document.getElementsByTagName("canvas")[0];  
if (canvas.getContext) {  
	var context = canvas.getContext("2d");  
	// 开始路径
	context.beginPath();
	// 绘制外圆
	context.arc(100, 100, 99, 0, 2 * Math.PI, false);
	// 绘制内圆
	context.moveTo(194, 100);
	context.arc(100, 100, 94, 0, 2 * Math.PI, false);
	// 绘制分针
	context.moveTo(100, 100);
	context.lineTo(100, 15);
	// 绘制时针
	context.moveTo(100, 100);
	context.lineTo(35,100);
	// 描边路径
	context.stroke();
	context.font = "15px solid Arial";
	context.textAlign = "center";
	context.textBaseine= "middle";
	context.fillText("12", 100, 20);
	context.textAlign = "start";
	context.fillText("12", 100, 40);
	context.textAlign = "end";
	context.fillText("12", 100, 60);
}

在需要把文本控制在某一区域中时,2D上下文提供了辅助确定文本大小的方法measureText(),该方法接收一个参数即要绘制的文本,利用font、textAlign、textBaseline的当前值计算指定文本的大小。返回一个TextMetrics对象,该对象目前只包含指示以像素计的指定字体宽度的width属性,但将来还会增加更多属性。

var canvas = document.getElementsByTagName("canvas")[0];  
if (canvas.getContext) {  
	var context = canvas.getContext("2d");  
	var fontSize = 100;
	context.font = fontSize + "px Arial";
	while (context.measureText("Hello world").width > 140) {
		fontSize--;
		context.font = fontSize + "px Arial";
	}
	context.fillText("Hello world", 10, 10);
}
关于2D上下文的更多应用详见:http://blog.csdn.net/zhouziyu2011/article/details/66474969

本文转载:CSDN博客