Canvas---Canvas變換與操作

平移

Canvas類提供了一個translate()方法就是用來平移畫布,以左上角爲原點,向右爲x軸正方向,向下爲y軸正方向。

將畫布沿着x軸和y軸的正方向都移動200像素之後,在畫布上繪製一個圖形:

canvas.translate(200,200);
        RectF rectF=new RectF(0,0,400,200);
        canvas.drawRect(rectF,paint);

發現,當前繪製的矩形距離屏幕的訂點有一段距離。

屏幕顯示與Canvas的關係

在看其他操作之前,需要知道屏幕顯示和Canvas的關係如何,首先看一個例子:先在畫布上繪製一個矩形,隨後平移畫筆,接着在相同的位置再繪製一個矩形,看一下兩者是否重合:

paint.setStyle(Paint.Style.STROKE);
        RectF rectF=new RectF(0,0,400,200);
        canvas.drawRect(rectF,paint);
        canvas.translate(200,200);
        paint.setColor(Color.RED);
        canvas.drawRect(rectF,paint);

很明顯的看出,兩者並不重合。在這裏,需要知道Canvas是一個很虛幻的概念,相當於一個透明圖層(用過PS的同學應該都知道),每次Canvas畫圖時(即調用Draw系列函數),都會產生一個透明圖層,然後在這個圖層上畫圖,畫完之後覆蓋在屏幕上顯示。所以第二次繪製矩形的時候,其實已經使用了一個新的畫布。總結來說,有如下幾點注意點:
**1、每次調用canvas.drawXXXX系列函數來繪圖進,都會產生一個全新的Canvas畫布。
2、如果在DrawXXX前,調用平移、旋轉等函數來對Canvas進行了操作,那麼這個操作是不可逆的!每次產生的畫布的最新位置都是這些操作後的位置。(關於Save()、Restore()的畫布可逆問題的後面再講)
3、在Canvas與屏幕合成時,超出屏幕範圍的圖像是不會顯示出來的。**

旋轉

畫布的旋轉操作默認是圍繞着原點來操作的,Canvas提供了一個可以指定旋轉點的方法:

void rotate(float degrees)
void rotate (float degrees, float px, float py)

第一個構造函數直接輸入旋轉的度數,正數是順時針旋轉,負數指逆時針旋轉,它的旋轉中心點是原點(0,0)
第二個構造函數除了度數以外,還可以指定旋轉的中心點座標(px,py)

下面看一個簡單的Canvas旋轉操作:

paint.setStyle(Paint.Style.STROKE);
        RectF rectF=new RectF(0,0,400,200);
        canvas.drawRect(rectF,paint);
        canvas.rotate(45,200,200);
        paint.setColor(Color.RED);
        canvas.drawRect(rectF,paint);

縮放
下面是一個對Canvas的縮放操作:

paint.setStyle(Paint.Style.FILL);
        RectF rectF=new RectF(0,0,200,100);
        canvas.drawRect(rectF,paint);

        paint.setColor(Color.GREEN);
        canvas.scale(0.5f,1);
        canvas.drawRect(rectF,paint);

扭曲

類似於PS中的斜切效果,兩個參數,分別是x軸和y軸傾斜的度數

void skew (float sx, float sy)

float sx:將畫布在x方向上傾斜相應的角度,sx傾斜角度的tan值,
float sy:將畫布在y軸方向上傾斜相應的角度,sy爲傾斜角度的tan值,

 paint.setStyle(Paint.Style.STROKE);
        RectF rectF=new RectF(0,0,400,200);
        canvas.drawRect(rectF,paint);
        paint.setColor(Color.RED);
        canvas.skew(1.732f,0);
        canvas.drawRect(rectF,paint);

裁剪畫布
裁剪畫布是利用Clip系列函數,通過與Rect、Path、Region取交、並、差等集合運算來獲得最新的畫布形狀。除了調用Save、Restore函數以外,這個操作是不可逆的,一但Canvas畫布被裁剪,就不能再被恢復!
Clip系列的方法有如下這些:

boolean clipPath(Path path)
boolean clipPath(Path path, Region.Op op)
boolean clipRect(Rect rect, Region.Op op)
boolean clipRect(RectF rect, Region.Op op)
boolean clipRect(int left, int top, int right, int bottom)
boolean clipRect(float left, float top, float right, float bottom)
boolean clipRect(RectF rect)
boolean clipRect(float left, float top, float right, float bottom, Region.Op op)
boolean clipRect(Rect rect)
boolean clipRegion(Region region)
boolean clipRegion(Region region, Region.Op op)

先看一個裁剪矩形的方法:

  canvas.drawColor(Color.GREEN);
        RectF rectF=new RectF(200,200,600,400);
        canvas.clipRect(rectF);
        canvas.drawColor(Color.RED);

畫布的保存與恢復

Save():每次調用Save()函數,都會把當前的畫布的狀態進行保存,然後放入特定的棧中;
restore():每當調用Restore()函數,就會把棧中最頂層的畫布狀態取出來,並按照這個狀態恢復當前的畫布,並在這個畫布上做畫。

爲了更好地使用上面兩個函數,在上一個例子上進行修改:

 canvas.drawColor(Color.GREEN);
        canvas.save();  //保存
        RectF rectF=new RectF(200,200,600,400);
        canvas.clipRect(rectF);
        canvas.drawColor(Color.RED);
        canvas.restore();
        canvas.drawColor(Color.BLUE);
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(Color.BLACK);
        paint.setTextSize(50);
        canvas.drawText("addas",100,100,paint);

上述例子中,畫布被裁剪爲一個小矩形,在本例中,使用了restore()進行了恢復,並將畫布的背景色改爲藍色。

現在多次使用save()和restore()方法,來了解一下Canvas畫布狀態的棧的概念:

 canvas.drawColor(Color.rgb(133,133,133));
        canvas.save();
         paint.setStyle(Paint.Style.FILL);
        canvas.clipRect(new RectF(50,50,850,850));
        canvas.drawColor(Color.RED);
        canvas.save();
        canvas.clipRect(new RectF(150,150,750,750));
        canvas.drawColor(Color.GREEN);
        canvas.save();
        canvas.clipRect(new RectF(250,250,650,650));
        canvas.drawColor(Color.GRAY);
        canvas.save();
        canvas.clipRect(new RectF(450,450,600,600));
        canvas.drawColor(Color.YELLOW);

        canvas.restore();
        canvas.drawColor(Color.rgb(0,0,0));

從上述的代碼中可以看出,共使用了4次save()操作,使用了一次restore()操作,可以看到最裏面的那個小正方向不再是黃色的,而是黑色的,說明當前Canvas的狀態爲400*400的正方形。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章