绘制图像
引入图像到canvas里需要以下两步基本操作:
-获得一个指向HTMLImageElement的对象或者另一个canvas元素的引用作为源,也可以通过提供一个URL的方式来使用图片
-使用drawImage()函数将图片绘制到画布上
获得需要绘制的图片
有几种方式可以获取到我们需要在canvas上使用的图片。
由零开始创建图像
1、新建图片对象,并将其src属性设置为图片路径。1
2var img = new Image(); // 创建一个img元素
img.src = 'myImage.png'; // 设置图片源地址
2、将绘制代码放在img.onload中,让绘制在图片加载完后执行.
1 | var img = new Image(); // 创建img元素 |
当脚本执行后,图片开始装载。若调用 drawImage 时,图片没装载完,那什么都不会发生(在一些旧的浏览器中可能会抛出异常)。因此你应该用load时间来保证不会在加载完毕之前使用这个图片.
使用相同页面内的图片
通过下列方法的一种来获得与canvas相同页面内的图片的引用:
-document.images集合
-document.getElementsByTagName()方法
- document.getElementById() //通过图片ID获得这个图片
使用其它 canvas 元素
和引用页面内的图片类似地,用 document.getElementsByTagName 或 document.getElementById 方法来获取其它 canvas 元素。但你引入的应该是已经准备好的 canvas。
一个常用的应用就是将第二个canvas作为另一个大的 canvas 的缩略图。
通过 data: url 方式嵌入图像
Data urls 允许用一串 Base64 编码的字符串的方式来定义一个图片。var img_src = 'data:image/gif;base64,R0lGODlhCwALAIAAAAAA3pn/ZiH5BAEAAAEALAAAAAALAAsAAAIUhA+hkcuO4lmNVindo7qyrIXiGBYAOw==';
其优点就是图片内容即时可用,无须再到服务器兜一圈。(还有一个优点是,可以将 CSS,JavaScript,HTML 和 图片全部封装在一起,迁移起来十分方便。)
缺点就是图像没法缓存,图片大的话内嵌的 url 数据会相当的长.
绘制图片
一旦获得了源图对象,我们就可以使用 drawImage 方法将它渲染到 canvas 里。drawImage 方法有三种形态.
drawImage(image, x, y)
其中image为图片对象名称,x 和 y 为绘图位置(图片左上角在画布中的坐标).1
2
3
4
5
6
7
8//画布300*300,图片200*200
var img = new Image();
img.src = "http://img3.imgtn.bdimg.com/it/u=1011179444,2282576107&fm=21&gp=0.jpg";
context.beginPath();
img.onload = function () {
context.drawImage(img,50,50);
}
drawImage(image, x, y, width, height):
- x和y :绘图位置(图片左上角在画布中的坐标)
- width和height:自定义图片在canvas中显示的大小
1
2
3
4
5
6
7
8//画布300*300,图片200*200
var img = new Image();
img.src = "http://img3.imgtn.bdimg.com/it/u=1011179444,2282576107&fm=21&gp=0.jpg";
context.beginPath();
img.onload = function () {
context.drawImage(img,0,0,300,300);
}
drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight):
选取图像的一部分矩形区域进行绘制.
- sx:图像上的x坐标
- sy:图像上的y坐标
- sWidth:矩形区域的宽度
- sHeight:矩形区域的高度
- dx:画在canvas的x坐标
- dy:画在canvas的y坐标
- dWidth:画出来的宽度
- dHeight:画出来的高度
前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。
图像裁剪c ontext.clip()
context.clip()只绘制封闭路径区域内的图像,不绘制路径外部图像,用的时候
先创建裁剪区域,再绘制图像.
如图所示。红边五角星就是裁切路径,所有在路径以外的部分都不会在 canvas 上绘制出来。1
2
图片像素处理
获取图片信息(使用图像数据)
getImageData(sx,sy,sw,sh)
- sx:cavas的x轴坐标点
- sy:canvas的y轴坐标点
- sw:距离x的宽度
- sh:距离y的高度
var imagedata=context.getImageData(sx,sy,sw,sh)
这里返回的对象是ImageData的实例。每个ImageData对象都有三个属性:width/height/data.
data
data属性是一个数组,保存着图像中每一个像素的数据。在data数组中,每一个像素用4个元素来保存,分别表示红、绿、蓝和透明度值。也就是[r1,g1,b1,a1,r2,g2,b2,a2,r3,g3,b3,a3…]这样一直排列下去.
数组的长度length = w h 4
在循环数组获取每个元素的时候,一般是要让i+=4这样获取每个像素
data数组中每个元素的值大小:0-255.
设置像素颜色:
context.putImageData(imagedata,dx,dy,dirtyX,dirtyY,dirtyWidth,dirtyHeight)
对imagedata数组中的各个像素的r、g、b、a值进行修改,再调用putImageData方法进行绘制
- imagedata:修改后的imagedata
- dx:重绘图像的起点横坐标(重绘的起点和原来的图像一致的话就会把原来的图形覆盖掉,看起来就像是原来的图像变成现在的图像一样)
- dy:重绘图像的起点纵坐标
- //以下可选参数,设置重绘的矩形范围,如果缺省,默认会重绘所有的imegedata
– dirtyX:矩形左上角x轴坐标
– dirtyY:矩形左上角y轴坐标
– dirtyWidth:矩形长度
– dirtyHeight:矩形高度
灰度效果
在rgba表示中,rgb值相同就一定是灰色.
获取每个像素的rgba值并将rgb值改为gray = (r+g+b)/3
重绘像素1
2
3
4
5
6
7
8
9
10
11
12
13//灰度处理
var imageData = context.getImageData(0,0,200,200);
var data = imageData.data;
for (var i = 0; i<200*200*4; i+=4){
var r = data[i];
var g = data[i+1];
var b = data[i+2];
var gray = (r+g+b)/3;
data[i] = gray; //r值
data[i+1] = gray; //g值
data[i+2] = gray; //b值
}
context.putImageData(imageData,200,0)
反色效果
在rgba表示中,rgb反色就是用255减去相应的数值
获取每个像素的rgba值并将rgb值改为 data[i] = 255-data[i]
重绘像素1
2
3
4
5
6
7
8
9//反色处理
var imageData = context.getImageData(0,0,200,200);
var data = imageData.data;
for (var j = 0; j<200*200*4; j+=4){
data[j] = 255-data[j];
data[j+1] = 255-data[j+1];
data[j+2] = 255-data[j+2];
}
context.putImageData(imageData,0,200);
图形输出
使用toDateURL()
方法,可以导出在canvas元素上绘制的图像。
这个方法接受一个参数,即图像的MIME类型格式。1
2
3
4
5
6var canvas=document.getElementById("canvas");
...
var imgURI=canvas.toDataURL("image/png");
var img=document.createElement("img");
img.src=imgURI;
document.body.appendChild(img);
图形组合 compositing
context.globalCompositeOperation=type
我们不仅可以在已有图形后面再画新图形,还可以用来遮盖,清除(比 clearRect 方法强劲得多)某些区域。
图形组合就是两个图形相互叠加了图形的表现形式,是后画的覆盖掉先画的呢,还是相互重叠的部分不显示等等,至于怎么显示就取决于type的值了
type:
-source-over(default):这是默认设置,新图形会覆盖在原有内容之上。
-source-in:新图形会仅仅出现与原有内容重叠的部分。其它区域都变成透明的。
-source-out:结果是只有新图形中与原有内容不重叠的部分会被绘制出来。
-source-atop:新图形中与原有内容重叠的部分会被绘制,并覆盖于原有内容之上。
-destination-over:会在原有内容之下绘制新图形。
-destination-in:原有内容中与新图形重叠的部分会被保留,其它区域都变成透明的。
-destination-out:原有内容中与新图形不重叠的部分会被保留。
-destination-atop:原有内容中与新内容重叠的部分会被保留,并会在原有内容之下绘制新图形
-lighter:两图形中重叠部分作加色处理。
-darker:两图形中重叠的部分作减色处理。
-copy:只有新图形会被保留,其它都被清除掉。
-xor:重叠的部分会变成透明。
注意:蓝色方块是先绘制的,即“已有的 canvas 内容”,红色圆形是后面绘制,即“新图形”。