本节书摘来自华章计算机《HTML5 Canvas游戏开发实战》一书中的第2章,第2.4节,作者:张路斌著, 更多章节内容可以访问云栖社区“华章计算机”公众号查看。
2.4 图片操作
无论我们开发的是应用程序还是游戏软件,都是离不开图片,没有图片就无法让整个页面漂亮起来。开发游戏的时候,游戏中的地图、背景、人物、物品等都是由图片组成的,所以图片的显示和操作非常重要。Canvas中提供了drawImage函数和putImageData函数来绘制图片,在本节中将一一讲解。
2.4.1 利用drawImage绘制图片
drawImage函数有3种函数原型,其语法如下:
drawImage(image, dx, dy);
drawImage(image, dx, dy, dw, dh);
drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);
第一个参数image是要绘制的对象,这个参数可以是HTMLImageElement、HTML-CanvasElement或者HTMLVideoElement,dx、dy是image在Canvas中定位的坐标值,dw、dh表示image在Canvas中即将绘制区域(相对dx和dy坐标的偏移量)的宽度和高度值,sx、sy是image所要绘制的起始位置,sw、sh表示image所要绘制区域(相对image的sx和sy坐标的偏移量)的宽度和高度值。
关于第一个参数,我们先使用HTML的标签来得到将要绘制的图片的数据。首先准备一张图片face.jpg,然后看代码清单2-23。
代码清单 2-23
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8" />
</head>
<body>
img标签<br />
<img id="face" src="face.jpg" alt="The Face" width="240" height="240" /><br />
canvas画板<br />
<canvas id="myCanvas" width="500" height="350">
你的浏览器不支持HTML5
</canvas>
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById("face");
ctx.drawImage(img,10,10);
</script>
</body>
</html>
代码解析
首先在html中加入标签。
<img id="face" src="face.jpg" alt="The Face" width="240" height="240" /><br />
然后在Canvas中通过< img>标签的id取得图片数据。
var img=document.getElementById("face");
最后用drawImage函数将图片绘制到画板上。
ctx.drawImage(img,10,10);
运行效果如图2-26所示。
上面的代码是通过标签来获取的,我们也可以通过JavaScript的Image对象来获取。具体使用方法如代码清单2-24所示。
代码清单 2-24
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById("face");
img.onload = function(){
ctx.drawImage(img,10,10);
};
</script>
代码解析
首先建立Image对象。
var image = new Image();
然后通过设置src属性,来载入图片。
image.src = "face.jpg";
接着添加onload事件侦听,当图片载入完成时将其绘制到画板上。
image.onload = function(){
ctx.drawImage(image,10,10);
};
运行效果如图2-27所示。
下面具体看一下drawImage函数的3种函数原型的用法与区别,如代码清单2-25所示。
代码清单 2-25
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var image = new Image();
image.src = "face.jpg";
image.onload = function(){
ctx.drawImage(image,10,10);
ctx.drawImage(image,260,10,100,100);
ctx.drawImage(image,50,50,100,100,260,130,100,100);
};
</script>
代码解析
下面的代码表示从坐标(10,10)开始绘制整张图片。
ctx.drawImage(image,10,10);
下面的代码表示从坐标(260,10)开始绘制整张图片到长100、宽100的矩形区域内。
ctx.drawImage(image,260,10,100,100);
下面的代码表示截取图片从 (50,50)到(100,100)的部分,从坐标(260,130)开始绘制,放到长100、宽100的矩形区域内。
ctx.drawImage(image,50,50,100,100,260,130,100,100);
运行效果如图2-28所示。
2.4.2 利用getImageData和putImageData绘制图片
将图片绘制到Canvas画板上还有另一种方法,就是使用putImageData(imgdata,dx,dy,sx,sy,sw,sh)函数。putImageData函数有7个参数,其中imgdata为像素数据,dx、dy是绘制图片的定位坐标值, sx、sy是imgdata所要绘制图片的起始位置,sw、sh是imgdata所要绘制区域(相对imgdata的sx和sy坐标的偏移量)的宽度和高度值。值得一提的是,这里面第4个参数以及其后的所有参数都可以省略,如果这些参数都省略了,则表示绘制整个imgdata。
在使用putImageData函数前,需要先用getImageData(x,y,w,h)函数得到像素数据,这里指的是从Canvas画板上取得所选区域的像素数据,它的4个参数分别是选择区域起点的坐标x和坐标y,选择区域的长和宽。putImageData(imgdata,dx,dy,x,y,w,h)函数则表示将所得到的像素数据描画到Canvas画板上形成图形。
下面是putImageData函数的使用过程,如代码清单2-26所示。
代码清单 2-26
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var image = new Image();
image.src = "face.jpg";
image.onload = function(){
ctx.drawImage(image,10,10);
var imgData=ctx.getImageData(50,50,200,200);
ctx.putImageData(imgData,10,260);
ctx.putImageData(imgData,200,260,50,50,100,100);
};
</script>
代码解析
图片数据读取完成后,首先将图片数据绘制到Canvas画板上。
ctx.drawImage(image,10,10);
然后用getImageData函数从画板上取得像素数据。
var imgData=ctx.getImageData(50,50,200,200);
将所取得的整个像素数据画到Canvas画板上。
ctx.putImageData(imgData,10,260);
将所取得的像素数据的一部分画到Canvas画板上。
ctx.putImageData(imgData,200,260,50,50,100,100);
运行效果如图2-29所示。
注意 代码清单2-26中使用了getImageData函数获取图片数据,此函数在Google Chrome等浏览器中会涉及跨域问题,所以无法直接在浏览器中浏览,必须通过服务器来访问。我们在第1章配置环境的时候已经安装了本地服务器,参照1.5节的内容,将本地的代码文件放到本地服务器上,就可以看到测试结果了。以后凡是用到getImageData函数的地方,一定要使用此方法进行测试,此处不赘述。
2.4.3 利用createImageData新建像素
createImageData函数有两种函数原型,其语法分别如下所示:
createImageData(sw, sh);
其一,返回指定大小的imageData对象。
createImageData(imagedata);
其二,返回与指定对象相同大小的imageData对象。
首先需要知道的是,通过createImageData返回的是一个空的imageData对象,必须要针对其像素进行赋值才能显示到Canvas画板上。下面我们通过例子来看看这两种原型的使用方法与区别,如代码清单2-27所示。
代码清单 2-27
<script type="text/javascript">
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var image = new Image();
image.src = "face.jpg";
image.onload = function(){
ctx.drawImage(image,10,10);
var imgData=ctx.getImageData(50,50,200,200);
var imgData01=ctx.createImageData(imgData);
for (i=0; i<imgData01.width*imgData01.height*4;i+=4){
imgData01.data[i+0]=255;
imgData01.data[i+1]=0;
imgData01.data[i+2]=0;
imgData01.data[i+3]=255;
}
ctx.putImageData(imgData01,10,260);
var imgData02=ctx.createImageData(100,100);
for (i=0; i<imgData02.width*imgData02.height*4;i+=4){
imgData02.data[i+0]=255;
imgData02.data[i+1]=0;
imgData02.data[i+2]=0;
imgData02.data[i+3]=155;
}
ctx.putImageData(imgData02,220,260);
};
</script>
代码解析
图片数据读取完成后,首先将图片数据绘制到Canvas画板上。
ctx.drawImage(image,10,10);
然后用getImageData函数从画板上取得像素数据。
var imgData=ctx.getImageData(50,50,200,200);
使用createImageData返回与imgData相同大小的ImageData对象。
var imgData01=ctx.createImageData(imgData);
下面imgData01进行赋值。
for (i=0; i<imgData01.width*imgData01.height*4;i+=4){
imgData01.data[i+0]=255;
imgData01.data[i+1]=0;
imgData01.data[i+2]=0;
imgData01.data[i+3]=255;
}
利用putImageData将imgData01画到Canvas画板上。
ctx.putImageData(imgData01,10,260);
使用createImageData返回一个大小为100×100的ImageData对象。
var imgData02=ctx.createImageData(100,100);
对imgData02进行赋值。
for (i=0; i<imgData02.width*imgData02.height*4;i+=4){
imgData02.data[i+0]=255;
imgData02.data[i+1]=0;
imgData02.data[i+2]=0;
imgData02.data[i+3]=155;
}
利用putImageData将imgData02画到Canvas画板上。
ctx.putImageData(imgData02,220,260);
运行效果如图2-30所示。