日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關咨詢
選擇下列產品馬上在線溝通
服務時間:8:30-17:00
你可能遇到了下面的問題
關閉右側工具欄

新聞中心

這里有您想知道的互聯網營銷解決方案
使用JavaScript和Canvas開發(fā)游戲之使用Canvas

3、通過Canvas元素實現高級圖像操作

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

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

這篇文章將帶領大家學習使用JavaScript和Canvas元素操作圖像了幾種不同的方式,這些方式在Canvas元素出現之前是不可能的事兒。

上一篇文章演示了如何利用Canvas實現一個基本的圖像動畫。那個例子很簡單,同樣的效果通過修改IMG或DIV等標準HTML元素的一些屬性,照樣也可以輕易實現。下面我們就來演示一下畫布元素的高級應用,展示一下它的真正威力。

首先,還是準備一個HTML頁面。

 
 
 
  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.    

與上個一例子的HTML頁面相比,唯一的區(qū)別就是添加了一些按鈕。單擊這些按鈕,就會設置currentFunction變量(稍后介紹)的值,用以改變在渲染循環(huán)中運行的函數。

以下是 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"; //還是第一個例子中的圖像
  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. }

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

◆ FPS:每秒多少幀

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

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

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

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

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

◆ currentTime:應用已經運行了多少秒

◆ sineWave:0到1之間的一個值,用于控制圖像的運動

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

◆ canvas:畫布元素的引用

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

然后,跟前面一樣,要設置在window的onload事件發(fā)生時立即調用init函數(關于init函數的介紹,請參見上一篇文章)。

draw函數

下面來看一看draw函數:

 
 
 
  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. }

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

標準的正弦函數能夠在-1到1之間產生非常完美的波形圖。首先,我們通過遞增currentTime變量來反映動畫已經運行了多長時間,然后再利用這個值在正弦曲線上找到一個點。給正弦函數返回的值(從-1到1)先加1再除以2,就可以把它們轉換成0到1這個范圍內的值。

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

然后,調用clearRect方法清空畫布,以便為后面的繪圖準備一個干凈的版面。

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

應用到畫布上面的效果是可以累積的,因而就可以利用幾個簡單的函數來“組合”出效果來。例如,在向屏幕上繪制之前,可能會有一艘飛船需要旋轉、變換和縮放。因為所有效果都對畫布起作用,所以這些效果會應用到將被繪制在屏幕上的所有對象,而不僅僅是某一幅圖像或某一個形狀(比如一艘飛船)。

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

◆ 調用save函數(保存當前的繪制狀態(tài))

◆ 旋轉、變換和縮放上下文

◆ 繪制飛船

調用restore函數,移除自上一次調用save方法以來所添加的任何效果,也就是撤銷之前的變化

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

 
 
 
  1. context2D.save();

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

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

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

 
 
 
  1. currentFunction();

為圖像應用完效果之后,就可以把它繪制到畫布上面了。所以,接下來就是調用drawImage來繪圖。

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

最后,再調用restore函數,把自調用save函數以來應用的所有效果從畫布上移除。

 
 
 
  1. context2D.restore();

alpha函數

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

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

shear函數

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

切變操作是通過transform函數向畫布應用一個矩陣來實現的。變換矩陣本身就是一個值得研究的主題,但對我們來說,如果不想理解背后的數學原理,可以在網上找到很多標準的2D變換矩陣(http://en.wikipedia.org/wiki/Transformation_matrix#Examples_in_2D_graphics),直接使用transform函數來應用它們即可。所謂切變,其實就是把圖像的頂部或底部推到一邊。

scale函數

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

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

rotate函數

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

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

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


網站題目:使用JavaScript和Canvas開發(fā)游戲之使用Canvas
文章起源:http://www.dlmjj.cn/article/djiocgs.html