PHP前端开发

Html5 Canvas Image的图文代码详解(二)

百变鹏仔 2个月前 (10-18) #H5教程
文章标签 详解

上一篇,主要讲了canvas提供的基本的image api;

本篇我们使用canvas提供的Image Api及变换,来实现一些实例:小车的简单运动、简单游戏地图、图像的平移缩放;

以下应用中使用到的图片:

图片1:tanks--[32*32]*8--tanks.png图片2:map--[32*32]*4--map.png

立即学习“前端免费学习笔记(深入)”;

 

 

 


我们在Canvas上(50,50)的位置上显示tanks的前1/8部分(第一个tank),如何做呢?我们用part of image api;

context.drawImage(tanks,0,0,32,32,50,50,32,32);

如果要使当前的tank旋转90度如何实现呢?

Canvas中旋转操作不管是针对shape、text还是image都是一样的;

首先,要把canvas的current state压入堆栈:context.save();

然后启动变换:context.setTransform(1,0,0,1,0,0);

我们要以tank自身为中心旋转90度,所以,要把原点平移到tank的中心;

tank的位置(x,y)是(50,50),大小size(w,h)是(32,32);所以它的中心点为(x+w/2,y+h/2);

平移原点:context.translate(50 + 16, 50 + 16);

旋转:context.rotate(90*Math.PI/180);

且记:本来是要在canvas的(50,50)位置绘制图片,平移原点后,该位置坐标就变成(-16,-16);

绘制图片:context.drawImage(tanks, 0, 0, 32, 32, -16, -16, 32, 32);

图片旋转---完整代码<!DOCTYPE html><html><head><meta charset="utf-8" /><title>Images</title><script type="text/javascript" src="../script/modernizr-latest.js"></script><script type="text/javascript">window.addEventListener("load", eventWindowLoaded, false);function eventWindowLoaded() {canvasApp();}function canvasSupport() {return Modernizr.canvas;}function canvasApp() {if(!canvasSupport()) {return;}var theCanvas = document.getElementById("canvasOne");var context = theCanvas.getContext("2d");var tanks = new Image();tanks.addEventListener(&#39;load&#39;, eventLoaded, false);tanks.src = "tanks.png";var x = 50;var y = 50;function eventLoaded() {drawScreen();}function drawScreen() {context.fillStyle = "#aaaaaa";context.fillRect(0, 0, 500, 500);context.save();context.setTransform(1, 0, 0, 1, 0, 0)context.translate(x + 16, y + 16);var angleInRadians = 90 * Math.PI / 180;context.rotate(angleInRadians);context.drawImage(tanks, 0, 0, 32, 32, -16, -16, 32, 32);context.restore();}}</script></head><body><div style="position: absolute; top: 50px; left: 50px;"><canvas id="canvasOne" width="500" height="500">Your browser does not support HTML5 Canvas.</canvas></div></body></html>

轮子转动动画

tanks一共有8个tank,每个图大小为(32,32);

如果我们要在(50,50)的位置上显示第2个tank,如果做呢?

第2个:context.drawImage(tanks, 32*(2-1), 0, 32, 32, -16, -16, 32, 32);

第3个:context.drawImage(tanks, 32*(3-1), 0, 32, 32, -16, -16, 32, 32);

依次类推,第8个:context.drawImage(tanks, 32*(8-1), 0, 32, 32, -16, -16, 32, 32);

每个tank图片的不同之处,就在于其轮子部位,如果我们用定时器100ms来轮流显示这1到8个tank图片,就会看到一个tank轮子转动动画;

tank轮子转动动画--完整代码<!DOCTYPE html><html><head><meta charset="utf-8" /><title>Images</title><script type="text/javascript" src="../script/modernizr-latest.js"></script><script type="text/javascript">window.addEventListener("load", eventWindowLoaded, false);function eventWindowLoaded() {canvasApp();}function canvasSupport() {return Modernizr.canvas;}function canvasApp() {if(!canvasSupport()) {return;}var theCanvas = document.getElementById("canvasOne");var context = theCanvas.getContext("2d");var tanks = new Image();tanks.addEventListener(&#39;load&#39;, eventLoaded, false);tanks.src = "tanks.png";//控制取第几个tankvar animationFrames = [0,1,2,3,4,5,6,7];var frameIndex = 0;//当前动画帧//tank的显示位置var x = 50;var y = 50;function eventLoaded() {startUp();}function drawScreen() {context.fillStyle = "#aaaaaa";context.fillRect(0, 0, 500, 500);context.save();context.setTransform(1, 0, 0, 1, 0, 0)context.translate(x + 16, y + 16);var angleInRadians = 90 * Math.PI / 180;context.rotate(angleInRadians);var sourceX = animationFrames[frameIndex] * 32;//每次取图片的X位置context.drawImage(tanks, sourceX, 0, 32, 32, -16, -16, 32, 32);context.restore();frameIndex++;//循环动画控制if(frameIndex == animationFrames.length) {frameIndex = 0;}}//计时器function startUp() {setInterval(drawScreen, 100);}}</script></head><body><div style="position: absolute; top: 50px; left: 50px;"><canvas id="canvasOne" width="500" height="500">Your browser does not support HTML5 Canvas.</canvas></div></body></html>

tank的水平移动效果实现起来就易如反掌啦,只要每次改变每一帧动画中,tank图片的显示的x位置就ok;

fcuntion drawScreen(){x=x+1;…………} 大家运行,看看效果!!!

我们定义一个320*320大小的Canvas,用图片map来绘制一个简单的游戏地图;

图片map共有四副小图,均是32*32:主背景、障碍、顶部底部砖块、左边右边砖块;

首先,我们把Canvas划分成10*10的小格子,每一个小格子的大小分别是32*32,刚好跟图片大小相同;

然后我们来定义一个二维数组来存放每一个小格子所要显示的图片的索引;

再用一个二层循环绘制图片,地图出来了;

先看看效果图:

简单的游戏地图--完整代码<!DOCTYPE html><html><head><meta charset="utf-8" /><title>Images</title><script type="text/javascript" src="../script/modernizr-latest.js"></script><script type="text/javascript">window.addEventListener("load", eventWindowLoaded, false);function eventWindowLoaded() {canvasApp();}function canvasSupport() {return Modernizr.canvas;}function canvasApp() {if(!canvasSupport()) {return;}var theCanvas = document.getElementById("canvasOne");var context = theCanvas.getContext("2d");var tileSheet = new Image();tileSheet.addEventListener(&#39;load&#39;, eventLoaded, false);tileSheet.src = "map.png";var mapRows = 10;var mapCols = 10;var Map = [[3, 2, 2, 2, 0, 2, 2, 2, 2, 3], [0,0,0,0,0,0,0,0,0, 0], [3,0, 1,0, 1,0, 1,0,0, 3], [3, 1,0,0, 1,0,0, 1,0, 3], [3,0,0,0, 1, 1,0, 1,0, 3], [3,0,0, 1,0,0,0, 1,0, 3], [3,0,0,0,0,0,0, 1,0, 3], [0,0, 1,0, 1,0, 1,0,0, 0], [3,0,0,0,0,0,0,0,0, 3], [3, 2, 2, 2,0, 2, 2, 2, 2, 3]];function eventLoaded() {drawScreen()}function drawScreen() {for(var rowCtr = 0; rowCtr < mapRows; rowCtr++) {for(var colCtr = 0; colCtr < mapCols; colCtr++) {var cur = Map[rowCtr][colCtr];var sourceX = cur * 32;context.drawImage(tileSheet, sourceX, 0, 32, 32, colCtr * 32, rowCtr * 32, 32, 32);}}}}</script></head><body><div style="position: absolute; top: 50px; left: 50px;"><canvas id="canvasOne" width="320" height="320">Your browser does not support HTML5 Canvas.</canvas></div></body></html>

再分享一个Image Api的应用:

图像的平移缩放<!DOCTYPE html><html><head><meta charset="utf-8" /><title>Pan</title><script type="text/javascript" src="../script/modernizr-latest.js"></script><script type="text/javascript">window.addEventListener("load", eventWindowLoaded, false);function eventWindowLoaded() {canvasApp();}function canvasSupport() {return Modernizr.canvas;}function canvasApp() {if(!canvasSupport()) {return;}var theCanvas = document.getElementById("canvasOne");var context = theCanvas.getContext("2d");var panImg = new Image();panImg.addEventListener(&#39;load&#39;, eventPhotoLoaded, false);panImg.src = "pan.jpg";var windowWidth = 500;var windowHeight = 500;var windowX = 0;var windowY = 0;var currentScale = 1;var minScale = .2var maxScale = 3;var scaleIncrement = 0.1;function eventPhotoLoaded() {startUp();}function drawScreen() {context.fillStyle = "#ffffff";context.fillRect(0, 0, 500, 500);context.drawImage(panImg, windowX, windowY, windowWidth, windowHeight, 0, 0, windowWidth * currentScale, windowHeight * currentScale);}function startUp() {setInterval(drawScreen, 100);}document.onkeydown = function(e) {e = e ? e : window.event;switch (e.keyCode) {case 38://upwindowY -= 10;if(windowY < 0) {windowY = 0;}break;case 40://downwindowY += 10;if(windowY > photo.height - windowHeight) {windowY = photo.height - windowHeight;}break;case 37://leftwindowX -= 10;if(windowX < 0) {windowX = 0;}break;case 39://rightwindowX += 10;if(windowX > photo.width - windowWidth) {windowX = photo.width - windowWidth;}break;case 109://-currentScale -= scaleIncrement;if(currentScale < minScale) {currentScale = minScale;}break;case 107://+currentScale += scaleIncrement;if(currentScale > maxScale) {currentScale = maxScale;}}}}</script></head><body><div style="position: absolute; top: 50px; left: 50px; padding:5px solid #000000"><canvas id="canvasOne" width="500" height="500">Your browser does not support HTML5 Canvas.</canvas></div></body></html>

该代码中,有一个图片"pan.jpg",大家随便找一个比较大的图就可以;

快运行,看看效果吧!