預設情況下,一個畫布的坐标空間會使用畫布的左上角 (0,0) 作為原點,x 值向右增加,y 值向下增加。這個坐标空間中的機關通常會被轉換為像素,然後,可通過轉換坐标空間在繪圖過程中實作移動、縮放或旋轉等操作。這些操作是通過 translate()、scale() 和 rotate()等方法來實作的,它們會對畫布的變換矩陣産生影響。
3.1.1 放大與縮小
我們用scale函數來實作圖形的放大和縮小。
其函數原型如下:
其中,第一個參數x表示在x軸進行縮放,即水準縮放,第二個參數 y表示在y軸上進行縮放,即在豎直方向上進行縮放。
具體實作方法如代碼清單3-1所示。
代碼清單 3-1
運作後的效果如圖3-1所示。
下面解釋一下代碼清單3-1的代碼。首先,以頁面上的坐标(10,10)為起點開始畫了一個寬150、高100的黑色矩形,如下所示:
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLzkjZldjZkN2YxgTY0ImY3QTYlFmNxUGMwETY2IDO1YWNyATOhJGOl9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
然後,沿着x軸和y軸方向将其值放大3倍,并用同樣的代碼重新畫一個灰色的矩形,如下所示:
從運作效果圖可以看到,雖然用了同樣的代碼,但是第二次畫的灰色矩形被放大了3倍,并且起始坐标值也一起被放大了3倍。
上述代碼清單3-1實作了放大功能,那麼現在來看看縮小功能如何實作,如代碼清單3-2所示。
代碼清單 3-2
運作後的效果如圖3-2所示。
在代碼清單3-2中,同樣先畫出了一個黑色矩形,然後沿着x軸和y軸方向上分别将其值縮小到了0.5倍,并用同樣的代碼重新畫了一個灰色的矩形。
從運作效果圖可以看到,雖然用了同樣的代碼,但是第二次畫的灰色矩形被縮小為原來的0.5倍了,并且起始坐标值也一起縮小了0.5倍。
另外還需要了解的是,使用scale函數時,如果将參數設定為負數,還可以使圖形翻轉,比如代碼清單3-3就實作了豎直方向的翻轉。
代碼清單 3-3
運作效果如圖3-3所示。
3.1.2 平移
使用translate函數可以實作對圖形進行平移的功能。
其中,第一個參數x表示在x軸進行平移,即在水準方向上平移,第二個參數 y表示在y軸上進行縮放,即在豎直方向上平移。
具體的實作方法如代碼清單3-4所示。
代碼清單 3-4
運作效果如圖3-4所示。
在代碼清單3-4中的如下代碼表示在水準方向上向右平移50,在豎直方向上向下平移100,圖3-4中灰色矩形是平移之後的效果。
3.1.3 旋轉
利用rotate函數可以實作圖形的旋轉功能。
這裡需要注意的是,傳入rotate裡的參數angle是弧度而不是角度。如果角度為angle,那麼換算為弧度就是angle*math.pi/180,具體實作方法如代碼清單3-5所示。
代碼清單 3-5
運作效果如圖3-5所示。
在圖3-5中灰色矩形是旋轉45度後的圖形,可以看到用rotate來實作旋轉時,是以canvas的起始坐标(0,0)為中心進行旋轉的。如果要想讓圖形以自己為中心旋轉,則需要使用3.1.2節中的translate函數,如代碼清單3-6所示。
代碼清單 3-6
運作效果如圖3-6所示。
在代碼清單3-6中,下面的代碼表示先将canvas的起始坐标向右移250,向下移75,即移至所畫矩形的中心處;然後開始旋轉45度;接着再将canvas的起始坐标向左移250,向上移75,即移回到原來位置,這樣就完成了圖形以自己為中心的旋轉。
3.1.4 利用transform矩陣實作多樣化的變形
上面分别講了縮放、平移以及旋轉的實作方法。其實所有這些變形都是可以通過變形矩陣transform來實作的。先來看看transform函數的定義。
transform函數的原型如下:
該函數的各個變量對應以下變換矩陣中相應位置的參數。
a c e
b d f
0 0 1
下面來說明如何使用這個變換矩陣來實作上面的各種變形。
1 . 縮放
假設原始坐标為(x,y),縮放後的坐标為(x1,y1),縮放的倍數分别為a和d,那麼就有下列公式:
是以,我們得到了如下矩陣公式。
這樣就可以用transform (a,0,0,d,0,0)來替換scale(a,d)了,如代碼清單3-7所示。
代碼清單 3-7
運作效果如圖3-7所示。
可以看到,這裡用代碼清單3-7實作了和代碼清單3-1一樣的功能。
平移
同樣,假設原始坐标為(x,y),平移後的坐标為(x1,y1),在x軸和y軸的平移量分别為e和f,那麼就有下列公式:
是以,我們得到如下矩陣公式。
這樣就可以用transform (1,0,0,1,e,f)來替換translate (e,f)了,如代碼清單3-8所示。
代碼清單 3-8
運作效果如圖3-8所示。
可以看到,這裡用代碼清單3-8實作了和代碼清單3-4一樣的功能。
3 . 旋轉
旋轉對應的矩陣公式如下。
現在可以用transform (cos , sin , –sin , cos ,0,0)來替換rotate ()了,如代碼清單3-9所示。
代碼清單 3-9
運作效果如圖3-9所示。
可以看到,這裡用代碼清單3-9實作了和代碼清單3-5一樣的功能。
這樣,我們就用transform完成了所有變形。另外,變換矩陣也可以通過settransform函數來實作,settransform的參數與transform一樣,不同的是,settransform函數是先消去之前的transform變換,然後重新進行變換的。為了區分transform和settransform,我們看看下面的例子,如代碼清單3-10所示。
代碼清單 3-10
運作效果如圖3-10所示。
在代碼清單3-10中,首先旋轉5度,然後再旋轉10度,是以第二次旋轉相當于旋轉了15度。
下面再看看代碼清單3-11中settransform的使用方法。
代碼清單 3-11
運作效果如圖3-11所示。
可以看到,第二次的旋轉沒有在第一次旋轉的基礎上進行,因為用settransform實作旋轉效果的時候,已經清除了上一個transform,是以隻旋轉了10度。
4 . 傾斜
接着來看一下如何實作圖像的傾斜效果。首先看圖3-12。
圖中的3個點p0、p1、p2遵循以下矩形公式。
将上面的矩形公式帶入settransform函數中,如代碼清單3-12所示。
代碼清單 3-12
運作效果如圖3-13所示。
上述傾斜效果也可以根據另外3個點來實作,看圖3-14。
圖中的3個點p1、p2、p3遵循以下矩形公式。
将上面的矩形公式代入settransform函數中,如代碼清單3-13所示。
代碼清單 3-13
運作效果如圖3-15所示。
5 . 圖檔的扭曲效果
根據以上所介紹的内容,已經可以做到傾斜、旋轉、平移和縮放4種基本變形,如圖3-16所示。
但是,對于非上述4種基本變形的特殊變形,就無法直接實作了。比如圖3-17中的扭曲變形效果。
這時候,就需要通過多種變形組合來實作。先對圖3-17進行分解,如圖3-18所示。
此時分解出的兩個圖形可分别看作是兩個基本變形的一部分,如圖3-19所示。
這樣一來就簡單了,隻需要實作兩個傾斜的變形,然後利用clip函數将圖檔的一部分繪制出來,就可以完成圖3-17中的效果了,如代碼清單3-14所示。
代碼清單 3-14
運作上面的代碼,就可以得到圖3-17的效果了。
解釋一下代碼清單3-14。首先看一下左半邊圖形的繪制。
上面這段代碼是以(80,0)、(320,40)和(0,200) 3個點為頂點繪制一個三角形,然後利用clip函數将這個三角形作為繪圖的可視區域。
上面的代碼是以剛才的三角形的3個頂點來進行傾斜變形的,這個變形的原理已經在代碼清單3-12中講過了。
上面的代碼是繪制圖檔,因為繪圖的可視區域隻是一個三角形,是以繪制完的圖檔隻有一部分。
右半邊圖形的繪制思路和左半邊是一樣的。同時,兩次繪圖都加上了save()函數和restore()函數,這是為了讓兩次變形和繪圖互不幹涉。