http://blog.csdn.net/zhouziyu2011/article/details/65682406已经介绍了canvas及2D上下文的一些应用。

下面继续介绍2D上下文的其他应用。


1、变换

通过上下文的变换,可以将处理后的图像绘制到画布上。

可以通过如下方法来变换上下文:

① rotate(angle):围绕圆点旋转angle弧度;

② scale(x, y):缩放图像,在x方向乘以x,在y方向乘以y;

③ translate(x, y):将坐标圆点移动到(x, y),执行该变换后,坐标(0, 0)会变为之前由(x, y)表示的点;

④ Transform(m1_1, m1_2, m2_1, m2_2, dx, dy);直接修改变换矩阵,方法是乘以如下矩阵:

m1_1 m1_2 dx

m2_1 m2_2 dy

0 0 1

⑤ setTransform(m1_1, m1_2, m2_1, m2_2, dx, dy):将变换矩阵重置为默认状态,然后再调用transform()。

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.translate(100, 100);
	// 旋转表针
	context.rotate(1);
	// 绘制分针
	context.moveTo(0, 0);
	context.lineTo(0, -85);
	// 绘制时针
	context.moveTo(0, 0);
	context.lineTo(-65, 0);
	// 描边路径
	context.stroke();
} 

没有什么方法可以把上下文中的一切都重置回默认值,但有两个方法可以跟踪上下文的状态变化,若将来还要返回某组属性和变换的组合,可以调用save()方法,使当时的设置进入栈中存储,之后可以对上下文进行其他修改,要回到之前保存的设置时,可以调用save()方法返回一级。当然可以连续调用save()将更多设置保存到栈中,之后连续调用restore()则可以一级一级返回。

var canvas = document.getElementsByTagName("canvas")[0];  
if (canvas.getContext) {  
	var context = canvas.getContext("2d");  
	context.fillStyle = "red";
	context.save();
	context.fillStyle = "green";
	context.translate(100, 100);
	context.save();
	context.fillStyle = "blue";
	context.fillRect(0, 0, 100, 200); // 从(100, 100)开始绘制蓝色矩形
	context.restore();
	context.fillRect(10, 10, 100, 200); // 从(110, 110)开始绘制绿色矩形
	context.restore();
	context.fillRect(0, 0, 100, 200); // 从(0, 0)开始绘制红色矩形
}


2、绘制图像

2D上下文内置了对图像的支持,使用drawImage()可以把一幅图像绘制到画布上,该方法可以传入三种不同的参数组合:

① HTML<img>元素,绘制图像的起点的x和y坐标

② HTML<img>元素,绘制图像的起点的x和y坐标,绘制图像的宽度和高度

③ HTML<img>元素,源图像的x坐标,源图像的y坐标,源图像的宽度,源图像的高度,目标图像的x坐标,目标图像的y坐标,目标图像的宽度,目标图像的高度。

④ HTML<canvas>元素,绘制图像的起点的x和y坐标

⑤ HTML<canvas>元素,绘制图像的起点的x和y坐标,绘制图像的宽度和高度

⑥ HTML<canvas>元素,源图像的x坐标,源图像的y坐标,源图像的宽度,源图像的高度,目标图像的x坐标,目标图像的y坐标,目标图像的宽度,目标图像的高度。

注意:使用drawImage()方法和其他方法可以对图像进行各种基本操作,操作的结果可以通过toDataURL()方法获得,但图像不能来自其他域,若图像来自其他域,调用toDataURL()会抛出一个错误。

var img = new Image();
img.src = "images/img4.jpg"; 
var canvas = document.getElementsByTagName("canvas")[0];    
if (canvas.getContext) {    
    var context = canvas.getContext("2d");    
    context.drawImage(img, 30, 30);  
    context.drawImage(img, 100, 100, 100, 100);  
    context.drawImage(img, 100, 100, 100, 100, 50, 50, 50, 50);  
}


3、阴影

2D上下文会根据以下几个属性的值,自动为形状或路径绘制出阴影:

shadowColor:用CSS颜色格式表示的阴影颜色,默认为黑色;

shadowOffsetX:形状或路径x轴方向的阴影偏移量,默认为0;

shadowOffsetY:形状或路径y轴方向的阴影偏移量,默认为0;

shadowBlur:模糊的像素数,默认为0,即不模糊。

var canvas = document.getElementsByTagName("canvas")[0];  
if (canvas.getContext) {  
	var context = canvas.getContext("2d");  
	context.shadowOffsetX = 10;
	context.shadowOffsetY = 10;
	context.shadowBlur = 10;
	context.shadowColor = "grey";
	context.fillStyle = "red";
	context.fillRect(20, 20, 100, 100);
	context.fillStyle = "blue";
	context.fillRect(50, 50, 100, 100);
}

不同浏览器对阴影的支持有所差异,IE9、Firefox4、Opera11的行为最为规范,其他浏览器都会有一些奇怪的现象,甚至根本不支持阴影。Chrome10以下版本不能正确地为描边形状应用实心阴影;Chrome及Safari5以下版本在为带透明像素的图像应用阴影时也会有问题——不透明部分的下方本来是该有阴影的却不见了;Safari不能给渐变图像应用阴影,其他浏览器则可以。

 

4、渐变

渐变由CanvasGradient实例表示。

1)线性渐变

① 使用createLinearGradient()方法创建渐变对象,此方法接收四个参数:起点的x坐标、起点的y坐标、终点的x坐标、终点的y坐标,返回一个CanvasGradient对象的实例。

② 使用addColorStop()方法指定色标,此方法接收两个参数:色标位置(一个0-1之间的数字)和CSS颜色值。

③ 把fillStyle或strokeStyle设置为该渐变对象,使用渐变来绘制形状或描边。

var canvas = document.getElementsByTagName("canvas")[0];  
if (canvas.getContext) {  
	var context = canvas.getContext("2d");  
	var gradient = createLinearGradient(30, 30, 80, 80);
	gradient.addColorStop(0, "red");
	gradient.addColorStop(1, "blue");
	context.fillStyle = gradient;
	context.fillRect(30, 30, 50, 50);
}

注意:为了让渐变覆盖整个矩形,而不是仅仅应用到矩形的一部分,矩形与渐变必须匹配才行,如context.fillRect(30, 30, 50, 50)只会显示部分渐变效果。因此,为了确保渐变与形状的对齐,可以考虑使用函数来确保坐标合适。

function createLinearGradient(context, x, y, width, height) {
	return context.createLinearGradient(x, y, x + width, y + height);
}
var canvas = document.getElementsByTagNames("canvas")[0];  
if (canvas.getContext) {  
	var context = canvas.getContext("2d");  
	var gradient = createLinearGradient(context, 100, 100, 300, 300);
	gradient.addColorStop(0, "red");
	gradient.addColorStop(1, "blue");
	context.fillStyle = gradient;
	context.fillRect(100, 100, 200, 200);
}


2)径向渐变(放射渐变)

① 使用createRadialGradient()方法创建渐变对象,此方法接收6个参数:起点圆的圆心x坐标、y坐标、半径和终点圆的圆心x坐标、y坐标、半径,返回一个CanvasGradient对象的实例。

② 使用addColorStop()方法指定色标,此方法接收两个参数:色标位置(一个0-1之间的数字)和CSS颜色值。

③ 把fillStyle或strokeStyle设置为该渐变对象,使用渐变来绘制形状或描边。

var canvas = document.getElementsByTagName("canvas")[0];    
if (canvas.getContext) {    
    var context = canvas.getContext("2d");    
    var gradient = context.createRadialGradient(150, 150, 10, 150, 150, 20); 
    gradient.addColorStop(0, "red");  
    gradient.addColorStop(1, "blue");  
    context.fillStyle = gradient;  
    context.fillRect(100, 100, 100, 100);  
    
}

由于创建比较麻烦,径向渐变不是那么容易控制,因此一般使用同心的起点圆和终点圆,这时只需考虑给两个圆设置不同的半径即可。

 

5、模式

模式其实就是重复的图像,可以用来填充或描边。

使用createPattern()方法可以创建一个新模式,传入两个参数:HTML<img>元素或<canvas>元素或<vedio>元素、用CSS颜background-repeat属性的值(repeat、repeat-x、repeat-y、no-repeat)。

var img = new Image();
img.src = "images/wrong.png";
var canvas = document.getElementsByTagName("canvas")[0];    
if (canvas.getContext) {    
    var context = canvas.getContext("2d");    
    var pattern = context.createPattern(img, "repeat");  
    context.fillStyle = pattern;  
    context.fillRect(0, 0, 100, 100);  
}

注意:模式与渐变一样,都是从画布的原点(0, 0)开始的,将fillStyle设置为模式对象,只表示某个特定的区域内显示重复的图像,而不是要从某个位置开始绘制重复的图像。

 

6、使用图像数据

2D上下文的一个长度在于:可以通过getImageData()取得原始图像数据,该方法接收四个参数:要取得原始图像数据的x和y坐标以及宽度和高度,返回的对象是ImageData的实例,每个ImageData对象都有三个属性:width、height和data,其中data属性是一个数组,保存着图像中每一个像素的数据,每一个像素用4个元素来保存,分别表示红、绿、蓝和透明度值,都介于0~255之间。

var imageData = context.getImageData(10, 10, 50, 50);
var data = imageData;
var red = data[0];
var green = data[1];
var blue = data[2];
var alpha = data[3];

既然能够通过getImageData()方法直接访问到原始图像数据,就能够以各种方式来操作这些数据。最典型的应用是实现彩色图片转换成黑白图片,详见:http://blog.csdn.net/zhouziyu2011/article/details/61915099


7、合成

globalAlpha和globalCompositionOperation属性会应用到2D上下文中所有绘制操作。

1)globalAlpha属性

globalAlpha是一个介于0和1之间的值,用于指定所有绘制的透明度,默认值为0。若所有后续操作都要基于相同的透明度,就可以先把globalAlpha设置为适当的值,绘制后再把它设置回默认值0。

var canvas = document.getElementsByTagName("canvas")[0];  
if (canvas.getContext) {  
	var context = canvas.getContext("2d");  
	context.globalAlpha = 0.5;
	context.fillStyle = "red";
	context.fillRect(30, 30, 50, 50);
	context.globalAlpha = 0;
}

2)globalCompositionOperation属性

globalCompositionOperation表示后绘制的图形怎样与先绘制的图形结合,值为字符串,可能的值如下:

① source-over(默认值):后绘制的图形位于先绘制的图形上方;

② source-in:后绘制的图形与先绘制的图形重叠的部分可见,其他部分完全透明;

③ source-out:后绘制的图形与先绘制的图形不重叠的部分可见,先绘制的图形完全透明;

④ source-atop:后绘制的图形与先绘制的图形重叠的部分可见,先绘制的图形不受影响;

⑤ destination-over:后绘制的图形位于先绘制的图形下方,只有之前透明像素下的部分才可见;

⑥ destination-in:后绘制的图形位于先绘制的图形下方,两者不重叠的部分完全透明;

⑦ destination-out:后绘制的图形擦除先绘制的图形重叠的部分;

⑧ destination-atop:后绘制的图形位于先绘制的图形下方,在两者不重叠的地方,先绘制的图形会变透明;

⑨ lighter:后绘制的图形与先绘制的图形重叠部分的值相加,使该部分变亮;

⑩ copy:后绘制的图形完全替代与之重叠的先绘制的图形;

⑪ xor:后绘制的图形与先绘制的图形重叠的部分执行异或操作。

var canvas = document.getElementsByTagName("canvas")[0];  
if (canvas.getContext) {  
	var context = canvas.getContext("2d");  
	context.fillStyle = "red";
	context.fillRect(30, 30, 50, 50);
	context.globalCompositionOperation = "destination-over";
	context.fillStyle = "blue";
	context.fillRect(50, 50, 50, 50);
}

不同浏览器对globalCompositionOperation属性的实现存在较大的差别,Safari和Chrome在这方面还有问题。


本文转载:CSDN博客