日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
使用JavaScript和Canvas開(kāi)發(fā)游戲之使用Canvas

3、通過(guò)Canvas元素實(shí)現(xiàn)高級(jí)圖像操作

我們提供的服務(wù)有:成都網(wǎng)站建設(shè)、網(wǎng)站建設(shè)、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、迎江ssl等。為近千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的迎江網(wǎng)站制作公司

http://www.brighthub.com/internet/web-development/articles/39509.aspx

這篇文章將帶領(lǐng)大家學(xué)習(xí)使用JavaScript和Canvas元素操作圖像了幾種不同的方式,這些方式在Canvas元素出現(xiàn)之前是不可能的事兒。

上一篇文章演示了如何利用Canvas實(shí)現(xiàn)一個(gè)基本的圖像動(dòng)畫。那個(gè)例子很簡(jiǎn)單,同樣的效果通過(guò)修改IMG或DIV等標(biāo)準(zhǔn)HTML元素的一些屬性,照樣也可以輕易實(shí)現(xiàn)。下面我們就來(lái)演示一下畫布元素的高級(jí)應(yīng)用,展示一下它的真正威力。

首先,還是準(zhǔn)備一個(gè)HTML頁(yè)面。

 
 
 
  1.  
  2.  
  3.     
  4.        JavaScript Platformer 2
  5.        
  6.        
  7.           body { font-family: Arial,Helvetica,sans-serif;}
  8.        
  9.     
  10.    
  11.       

  12.          
  13.             Game Development with Javascript and the canvas element
  14.          
  15.       

  16.       
  17.          

    Your browser does not support the canvas element.

  18.       
  19.       
  20.       Change Alpha
  21.       Shear
  22.       Scale
  23.       Rotate
  24.    

與上個(gè)一例子的HTML頁(yè)面相比,唯一的區(qū)別就是添加了一些按鈕。單擊這些按鈕,就會(huì)設(shè)置currentFunction變量(稍后介紹)的值,用以改變?cè)阡秩狙h(huán)中運(yùn)行的函數(shù)。

以下是 jsplatformer2.js 的代碼。

 
 
 
  1. // 每秒多少幀
  2. const FPS = 30;
  3. const SECONDSBETWEENFRAMES = 1 / FPS;
  4. const HALFIMAGEDIMENSION = 75;
  5. const HALFCANVASWIDTH = 300;
  6. const HALFCANVASHEIGHT = 200;
  7. var image = new Image();
  8. image.src = "jsplatformer2-smiley.jpg"; //還是第一個(gè)例子中的圖像
  9. var canvas = null;
  10. var context2D = null;
  11. var currentFunction = null;
  12. var currentTime = 0;
  13. var sineWave = 0;
  14. window.onload = init;
  15. function init()
  16. {
  17.    canvas = document.getElementById('canvas');
  18.    context2D = canvas.getContext('2d');
  19.    setInterval(draw, SECONDSBETWEENFRAMES * 1000);
  20.    currentFunction = scale;
  21. }
  22. function draw()
  23. {
  24.     currentTime += SECONDSBETWEENFRAMES;
  25.     sineWave = (Math.sin(currentTime) + 1) / 2;
  26.     context2D.clearRect(0, 0, canvas.width, canvas.height);
  27.     context2D.save();
  28.     context2D.translate(HALFCANVASWIDTH - HALFIMAGEDIMENSION, HALFCANVASHEIGHT - HALFIMAGEDIMENSION);
  29.     currentFunction();
  30.     context2D.drawImage(image, 0, 0);
  31.     context2D.restore();
  32. }
  33. function alpha()
  34. {
  35.     context2D.globalAlpha = sineWave;
  36. }
  37. function shear()
  38. {
  39.     context2D.transform(1, 0, (sineWave - 0.5), 1, 0, 0);
  40. }
  41. function scale()
  42. {
  43.     context2D.translate(HALFIMAGEDIMENSION * (1 - sineWave), HALFIMAGEDIMENSION * (1 - sineWave));
  44.     context2D.scale(sineWave, sineWave);
  45. }
  46. function rotate()
  47. {
  48.     context2D.translate(HALFIMAGEDIMENSION, HALFIMAGEDIMENSION);
  49.     context2D.rotate(sineWave * Math.PI * 2);
  50.     context2D.translate(-HALFIMAGEDIMENSION, -HALFIMAGEDIMENSION);
  51. }

跟前面一樣,這個(gè)JavaScript文件先定義了一些全局變量。

◆ FPS:每秒多少幀

◆ SECONDSBETWEENFRAMES:兩幀之間間隔的秒數(shù)(FPS的倒數(shù))

◆ HALFIMAGEDIMENSION:要繪制圖像的寬度/高度的一半,用于把圖像定位到畫布的中心點(diǎn)

◆ HALFCANVASWIDTH:畫布寬度的一半,用于配合HALFIMAGEDIMENSION使用,以便在畫布上居中圖像

◆ HALFCANVASHEIGHT:畫布高度的一半,用于配合HALFIMAGEDIMENSION使用,以便在畫布上居中圖像

◆ currentFunction:渲染循環(huán)(參見(jiàn)上一篇文章)中運(yùn)行的函數(shù)

◆ currentTime:應(yīng)用已經(jīng)運(yùn)行了多少秒

◆ sineWave:0到1之間的一個(gè)值,用于控制圖像的運(yùn)動(dòng)

◆ image:要在畫布上繪制的圖像

◆ canvas:畫布元素的引用

◆ context2D:畫布元素的2D上下文的引用

然后,跟前面一樣,要設(shè)置在window的onload事件發(fā)生時(shí)立即調(diào)用init函數(shù)(關(guān)于init函數(shù)的介紹,請(qǐng)參見(jiàn)上一篇文章)。

draw函數(shù)

下面來(lái)看一看draw函數(shù):

 
 
 
  1. function draw()
  2. {
  3.     currentTime += SECONDSBETWEENFRAMES;
  4.     sineWave = (Math.sin(currentTime) + 1) / 2;
  5.     context2D.clearRect(0, 0, canvas.width, canvas.height);
  6.     context2D.save();
  7.     context2D.translate(HALFCANVASWIDTH - HALFIMAGEDIMENSION, HALFCANVASHEIGHT - HALFIMAGEDIMENSION);
  8.     currentFunction();
  9.     context2D.drawImage(image, 0, 0);
  10.     context2D.restore();
  11. }

這個(gè)例子要演示4種效果:修改alpha值(透明度),以及縮放、旋轉(zhuǎn)和切變圖像。為了展示這些效果,需要基于某一范圍內(nèi)的值來(lái)應(yīng)用變化。變量sineWave就用來(lái)定義這個(gè)范圍值的基準(zhǔn)。

標(biāo)準(zhǔn)的正弦函數(shù)能夠在-1到1之間產(chǎn)生非常完美的波形圖。首先,我們通過(guò)遞增currentTime變量來(lái)反映動(dòng)畫已經(jīng)運(yùn)行了多長(zhǎng)時(shí)間,然后再利用這個(gè)值在正弦曲線上找到一個(gè)點(diǎn)。給正弦函數(shù)返回的值(從-1到1)先加1再除以2,就可以把它們轉(zhuǎn)換成0到1這個(gè)范圍內(nèi)的值。

 
 
 
  1. currentTime += SECONDSBETWEENFRAMES;
  2. sineWave = (Math.sin(currentTime) + 1) / 2;

然后,調(diào)用clearRect方法清空畫布,以便為后面的繪圖準(zhǔn)備一個(gè)干凈的版面。

 
 
 
  1. context2D.clearRect(0, 0, canvas.width, canvas.height);

應(yīng)用到畫布上面的效果是可以累積的,因而就可以利用幾個(gè)簡(jiǎn)單的函數(shù)來(lái)“組合”出效果來(lái)。例如,在向屏幕上繪制之前,可能會(huì)有一艘飛船需要旋轉(zhuǎn)、變換和縮放。因?yàn)樗行Ч紝?duì)畫布起作用,所以這些效果會(huì)應(yīng)用到將被繪制在屏幕上的所有對(duì)象,而不僅僅是某一幅圖像或某一個(gè)形狀(比如一艘飛船)。

其中,save和restore函數(shù)為應(yīng)用這些累積的效果提供了一種簡(jiǎn)單的機(jī)制,可以將應(yīng)用了這些效果的圖像或圖形繪制到畫布上,然后“撤銷”這些改變。后臺(tái)的操作是什么呢?save函數(shù)把當(dāng)前的繪制狀態(tài)推進(jìn)棧里,而restore函數(shù)則把最后一個(gè)狀態(tài)彈出棧。還拿前面提到的飛船為例,需要執(zhí)行下列操作:

◆ 調(diào)用save函數(shù)(保存當(dāng)前的繪制狀態(tài))

◆ 旋轉(zhuǎn)、變換和縮放上下文

◆ 繪制飛船

調(diào)用restore函數(shù),移除自上一次調(diào)用save方法以來(lái)所添加的任何效果,也就是撤銷之前的變化

在這里,我們就是要組合起來(lái)使用這兩個(gè)方法。首先,在把任何效果應(yīng)用到畫布之前,先保存繪制狀態(tài)。

 
 
 
  1. context2D.save();

保存了繪制狀態(tài)之后,就該應(yīng)用目標(biāo)效果了。為此,首先調(diào)用translate函數(shù),從而將隨后要繪制的圖像在畫布上居中。

 
 
 
  1. context2D.translate(HALFCANVASWIDTH - HALFIMAGEDIMENSION, HALFCANVASHEIGHT - HALFIMAGEDIMENSION);

接下來(lái),調(diào)用由變量currentFunction引用的函數(shù)。正是這些被引用的函數(shù),是讓圖像發(fā)生alpha(透明度)變化以及縮放、旋轉(zhuǎn)和切變的關(guān)鍵。這些函數(shù)我們稍后再介紹。

 
 
 
  1. currentFunction();

為圖像應(yīng)用完效果之后,就可以把它繪制到畫布上面了。所以,接下來(lái)就是調(diào)用drawImage來(lái)繪圖。

 
 
 
  1. context2D.drawImage(image, 0, 0);

最后,再調(diào)用restore函數(shù),把自調(diào)用save函數(shù)以來(lái)應(yīng)用的所有效果從畫布上移除。

 
 
 
  1. context2D.restore();

alpha函數(shù)

 
 
 
  1. function alpha()
  2. {
  3.     context2D.globalAlpha = sineWave;
  4. }

通過(guò)修改上下文對(duì)象的globalAlpha屬性,所有后續(xù)繪制操作的透明度都會(huì)被修改。將globalAlpha設(shè)置為0,意味著被繪制的任何對(duì)象都將完全透明,而將這個(gè)屬性設(shè)置為1,則意味著任何繪制操作都會(huì)保持原有的透明度級(jí)別。在此,我們通過(guò)修改這個(gè)globalAlpha屬性,可以實(shí)現(xiàn)笑臉的淡入和淡出效果。

shear函數(shù)

 
 
 
  1. function shear()
  2. {
  3.     context2D.transform(1, 0, (sineWave - 0.5), 1, 0, 0);
  4. }

切變操作是通過(guò)transform函數(shù)向畫布應(yīng)用一個(gè)矩陣來(lái)實(shí)現(xiàn)的。變換矩陣本身就是一個(gè)值得研究的主題,但對(duì)我們來(lái)說(shuō),如果不想理解背后的數(shù)學(xué)原理,可以在網(wǎng)上找到很多標(biāo)準(zhǔn)的2D變換矩陣(http://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_2D_graphics),直接使用transform函數(shù)來(lái)應(yīng)用它們即可。所謂切變,其實(shí)就是把圖像的頂部或底部推到一邊。

scale函數(shù)

 
 
 
  1. function scale()
  2.  {
  3.      context2D.translate(HALFIMAGEDIMENSION * (1 - sineWave), HALFIMAGEDIMENSION * (1 - sineWave));
  4. 56
  5.     context2D.scale(sineWave, sineWave);
  6.  }

顧名思義,scale(縮放)函數(shù)修改的是圖像的大小。但在此之前,我們還調(diào)用了一次transalte函數(shù)。這是為了讓縮放后的圖像在畫布上居中。如果你把這行代碼注釋掉,就會(huì)發(fā)現(xiàn)圖像會(huì)從左上角向右下角膨脹。調(diào)用translate函數(shù)就是為抵消其圓心的位移,讓圖像始終居中。

rotate函數(shù)

 
 
 
  1. function rotate()
  2. {
  3.     context2D.translate(HALFIMAGEDIMENSION, HALFIMAGEDIMENSION);
  4.     context2D.rotate(sineWave * Math.PI * 2);
  5.     context2D.translate(-HALFIMAGEDIMENSION, -HALFIMAGEDIMENSION);
  6. }

與scale函數(shù)類似,rotate(旋轉(zhuǎn))函數(shù)的作用也正如其名:旋轉(zhuǎn)圖像。與scale函數(shù)同樣類似的是,這里也額外調(diào)用了translate函數(shù)以確保圖像圍繞中心點(diǎn)而不是左上角旋轉(zhuǎn)。建議大家把對(duì)translate函數(shù)的調(diào)用注釋掉,自己看一看結(jié)果有什么不同。

剛剛我們看到了使用畫布元素實(shí)現(xiàn)的4種也還算簡(jiǎn)單的效果,這些效果使用標(biāo)準(zhǔn)的HTML元素幾乎是不可能做到的。其中,有的效果可以使用scale和rotate等內(nèi)置函數(shù)來(lái)實(shí)現(xiàn),而使用transform函數(shù)則可以完成大量的圖像操作(切變只是其中之一)。


文章標(biāo)題:使用JavaScript和Canvas開(kāi)發(fā)游戲之使用Canvas
標(biāo)題路徑:http://m.5511xx.com/article/djiocgs.html