HTML5- Canvas入門(六)


已經第六章了,也差不多接近尾聲,如果你從第一章耐心follow到本章結束,那你便能掌握canvas的大部分知識點(當然如果要精通,還是得多靠練習,做一些小案例)。

今天我們要學習的是canvas的變形轉換方法。

縮放方法scale()

在canvas中,如果我們需要縮放當前繪圖對象,可以利用 scale() 來實現,其語法為

ctx.scale( s_width, s_height );

s_width 和 s_height 表示要縮放的寬度或高度的縮放倍數,注意這兩個參數的值不再是像素值而是縮放倍數,比如1表示不縮放、0.5表示縮小50%、2.3表示放大2.3倍。我們來個例子:

<canvas id="myCanvas" width="400" height="350" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image();
img.src = "http://images.cnblogs.com/cnblogs_com/vajoy/558869/o_avatar.jpg";
img.onload = function(){
    ctx.globalAlpha = 0.3;  //設置全局透明度
    ctx.drawImage(img,0,0); 
    ctx.scale(1.2,1.2);
    ctx.drawImage(img,0,0); 
    ctx.scale(1.2,1.2);
    ctx.drawImage(img,0,0); 
}
</script>

注意我們這里動用了 ctx.globalAlpha 屬性,它表示全局透明度,其值為0-1,1表示不透明,0表示徹底透明。我們上方代碼設置全局透明度為0.3,表示后續繪制出來的任何對象其透明度都只有30%。效果如下:

要注意的一點是,在canvas對當前繪圖對象進行縮放時,其縮放中心點是畫布(0,0)的坐標原點。不僅僅是縮放,后續我們要介紹的其它變形方法,均是以畫布(0,0)坐標點為變形中心點的。

我們可以看下這個例子:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image();
img.src = "http://images.cnblogs.com/cnblogs_com/vajoy/558869/o_avatar.jpg";
img.onload = function(){
    ctx.globalAlpha = 0.5; 
    ctx.drawImage(img,10,10); 
    ctx.scale(2,2);
    ctx.drawImage(img,10,10); 
}

可以看到,由於相對畫布左上角的原點做了2倍縮放,故繪制的第二張圖片(即被放大2倍的圖片)距離畫布左上角的距離,是第一張的兩倍距離。

也就是說,第二次的 ctx.drawImage(img,10,10) 中的距離參數也同樣做了放大,實際在畫布上開始繪制的坐標變成了(10*2, 10*2),即(20,20)。

旋轉方法rotate()

我們可以通過 rotate() 方法對當前繪制對象進行旋轉,該方法只有一個參數:

ctx.rotate(angle);

參數angle指要旋轉的度數,還記得我們在第三章提到,度數要使用 Math.PI 為基准,你可以把一個 Math.PI 理解為180度,如下我們來把一張圖片旋轉30度(1/6*Math.PI):

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image();
img.src = "http://images.cnblogs.com/cnblogs_com/vajoy/558869/o_avatar.jpg";
img.onload = function(){
    ctx.globalAlpha = 0.5; 
    ctx.drawImage(img,10,10); 
    ctx.rotate(1/6*Math.PI);
    ctx.drawImage(img,10,10); 
}

於是圖片會相對畫布左上角原點做順時針30度的旋轉,如果你希望逆時針旋轉,可以將度數設為負值,比如 ctx.rotate(-1/6*Math.PI);  

位移方法translate()

在畫布繪制了一個對象后,我們可以通過 translate() 方法對畫布坐標進行相對X軸或Y軸方向的位移。其語法為:

ctx.translate( t_x, t_y );

t_x表示在x軸方向上的位移量,t_y表示在y軸方向上的位移量。我們來個示例:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image();
img.src = "http://images.cnblogs.com/cnblogs_com/vajoy/558869/o_avatar.jpg";
img.onload = function(){
    ctx.globalAlpha = 0.5; 
    ctx.drawImage(img,10,60); 
    ctx.globalAlpha = 1; 
    ctx.translate(50,-30);  //在x軸方向做50px的向右位移,在y軸方向做30px的向上位移
    ctx.drawImage(img,10,60); 
}

可以看到,新繪制的對象(不透明的圖片)相對第一張圖片(半透明的)在X軸、Y軸方向分別偏移了50px和-30px。

不過我們介紹 translate() 的時候表示該方法是對畫布坐標進行相對X軸或Y軸方向的位移,這個怎么理解?

上方的代碼里,兩次drawImage時,其開始繪制的坐標都是(10,60),我們先試着修改一下,把第二次繪圖代碼改為ctx.drawImage(img,30,30):

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image();
img.src = "http://images.cnblogs.com/cnblogs_com/vajoy/558869/o_avatar.jpg";
img.onload = function(){
    ctx.globalAlpha = 0.5; 
    ctx.drawImage(img,10,60); 
    ctx.globalAlpha = 1; 
    ctx.translate(50,-30); 
    ctx.drawImage(img,30,30); //修改參數,讓開始繪制的坐標跟上方的不同
}

效果如下:

那么對於這個效果的理解,我們可以看做“畫布的坐標系統”在X軸、Y軸方向分別偏移了50px和-30px。來張分析圖加深理解:

變形方法transform()

如果你是一名Transformer(變形金剛)的熱衷者,那么你對transform這個單詞自然也很了解。

在canvas中,我們可以對當前繪圖對象進行矩陣變形。我們先來看一下Adobe Fireworks里一個實用工具——扭曲工具的效果:

而 transform() 正是實現這種在水平方位或垂直方位做縮放、傾斜、偏移的效果。對應這些效果,它的參數有六個:

ctx.transform(a,b,c,d,e,f);

參數含義如下:

乍一看這參數貌似很混亂,其實不然,它是遵從數學矩陣公式規則的(點此查看詳細):

其中,x和y是元素最開始的坐標,x’ 和y’則是通過矩陣變換后得到新的坐標。通過3×3的變換矩陣,對原先的坐標施加變換,就能得到新的坐標了。

我們來個實例,讓圖片在原位置上縮小一倍、水平傾斜45度、垂直偏移50px:

<canvas id="myCanvas" width="260" height="400" style="border:solid 1px #CCC;">
您的瀏覽器不支持canvas,建議使用最新版的Chrome
</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image();
img.src = "http://images.cnblogs.com/cnblogs_com/vajoy/558869/o_avatar.jpg";
img.onload = function(){
    ctx.globalAlpha = 0.5;
    ctx.drawImage(img,0,0); 
    ctx.globalAlpha = 1;
    ctx.transform(0.5,1,0,0.5,0,50); //變形
    ctx.drawImage(img,0,0);
}
</script>

注意此處的“水平傾斜45度”,我們是給參數b賦值1,而不是Math.PI之類的角度值。

在CSS 3中,transform: skew(θx, θy); 就等價於 transform: matrix(tan(θx),0,0,tan(θy),0,0); 而transform()里的傾斜參數也是相當於 tan(傾斜角度) 計算后的值,由於 tan(45°)=1 ,故我們給參數b賦值1來實現水平傾斜45度的效果。

最后要介紹的是 setTransform() 方法,它跟 transform() 有着一樣的參數、實現着一樣的方法,不過 setTransform() 會重置所有曾設置過的變形數值。

怎么理解 transform() 跟 setTransform() 的區別呢?我們來看個例子:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image();
img.src = "http://images.cnblogs.com/cnblogs_com/vajoy/558869/o_avatar.jpg";
img.onload = function(){
    ctx.globalAlpha = 0.5;
    ctx.drawImage(img,0,0); 
    ctx.globalAlpha = 1;
    ctx.scale(0.5,0.5);   //縮小至0.5倍
    ctx.transform(0.5,0,0,0.5,0,0); //變形,再要求縮小至0.5倍
    ctx.drawImage(img,0,300);
}

執行后可以看到,transform() 在原有的縮小了0.5倍的基礎上,又把圖片繼續再縮小0.5倍,也就是畫出來的第二張圖片是第一張的1/4:

我們把 transform() 換成 setTransform() 試試:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = new Image();
img.src = "http://images.cnblogs.com/cnblogs_com/vajoy/558869/o_avatar.jpg";
img.onload = function(){
    ctx.globalAlpha = 0.5;
    ctx.drawImage(img,0,0); 
    ctx.globalAlpha = 1;
    ctx.scale(0.5,0.5);   //縮小至0.5倍
    ctx.setTransform(0.5,0,0,0.5,0,0); //變形,再要求縮小至0.5倍
    ctx.drawImage(img,0,300);
}

可以看到 setTransform() 重置了“縮放”效果,即一開始的 scale(0.5,0.5) 效果被pass掉了,你可以試着把 scale() 改為  scale(3.5,3.5),但它不會其任何作用。

你也可以做多次嘗試,你會發現 setTransform() 會很好地重置、覆蓋掉之前設置過的 scale()、translate()、transform() 變形數值。

本章就介紹到這,共勉~

donate


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM