Canvas之畫布操作
内容來自:安卓自定義View進階-Canvas之畫布操作
基本操作
位移
translate是坐标系的移動,位移是基于目前位置移動,而不是每次基于螢幕左上角的(0,0)點移動
// 繪制矩形
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawRect(new Rect(0, 0, 200, 200), mPaint);
// 在坐标原點繪制一個黑色圓形
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.FILL);
canvas.translate(200, 200);
canvas.drawCircle(100, 100, 100, mPaint);
// 在坐标原點繪制一個藍色圓形
mPaint.setColor(Color.BLUE);
canvas.translate(200,200);
canvas.drawCircle(0,0,100,mPaint);

縮放(scale)
縮放提供了兩個方法,如下:
public void scale (float sx, float sy)
public final void scale (float sx, float sy, float px, float py)
縮放的中心預設為坐标原點,而縮放中心軸就是坐标軸,第二個方法的
px
和
py
,用來控制縮放中心位置
// 将坐标系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);
RectF rect = new RectF(0,-400,400,0); // 矩形區域
mPaint.setColor(Color.BLACK); // 繪制黑色矩形
canvas.drawRect(rect,mPaint);
canvas.scale(0.5f,0.5f); // 畫布縮放
mPaint.setColor(Color.BLUE); // 繪制藍色矩形
canvas.drawRect(rect,mPaint);
使用第二種方法讓縮放中心位置稍微改變一下,如下:
// 将坐标系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);
RectF rect = new RectF(0,-400,400,0); // 矩形區域
mPaint.setColor(Color.BLACK); // 繪制黑色矩形
canvas.drawRect(rect,mPaint);
canvas.scale(0.5f,0.5f,200,0); // 畫布縮放 <-- 縮放中心向右偏移了200個機關
mPaint.setColor(Color.BLUE); // 繪制藍色矩形
canvas.drawRect(rect,mPaint);
當縮放比例為負數的時候會根據縮放中心軸進行翻轉
// 将坐标系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);
RectF rect = new RectF(0,-400,400,0); // 矩形區域
mPaint.setColor(Color.BLACK); // 繪制黑色矩形
canvas.drawRect(rect,mPaint);
canvas.scale(-0.5f,-0.5f); // 畫布縮放
mPaint.setColor(Color.BLUE); // 繪制藍色矩形
canvas.drawRect(rect,mPaint);
和位移(translate)一樣,縮放也是可以疊加的,如下的例子:
// 将坐标系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);
RectF rect = new RectF(-400,-400,400,400);
for (int i = 0; i < 20; i++) {
canvas.scale(0.9f, 0.9f);
canvas.drawRect(rect, mPaint);
}
旋轉
旋轉提供了兩種方法:
public void rotate (float degrees)
public final void rotate (float degrees, float px, float py)
第二種方法多出來的兩個參數依舊是控制旋轉中心點的
預設的旋轉中心依舊是坐标原點:
// 将坐标系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);
RectF rect = new RectF(0,-400,400,0); // 矩形區域
mPaint.setColor(Color.BLACK); // 繪制黑色矩形
canvas.drawRect(rect,mPaint);
canvas.rotate(180); // 旋轉180度 <-- 預設旋轉中心為原點
mPaint.setColor(Color.BLUE); // 繪制藍色矩形
canvas.drawRect(rect,mPaint);
改變旋轉中心位置:
// 将坐标系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);
RectF rect = new RectF(0,-400,400,0); // 矩形區域
mPaint.setColor(Color.BLACK); // 繪制黑色矩形
canvas.drawRect(rect,mPaint);
canvas.rotate(180,200,0); // 旋轉180度 <-- 旋轉中心向右偏移200個機關
mPaint.setColor(Color.BLUE); // 繪制藍色矩形
canvas.drawRect(rect,mPaint);
同樣旋轉也可以疊加
// 将坐标系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);
canvas.drawCircle(0,0,400,mPaint); // 繪制兩個圓形
canvas.drawCircle(0,0,380,mPaint);
for (int i=0; i<=360; i+=10){ // 繪制圓形之間的連接配接線
canvas.drawLine(0,380,0,400,mPaint);
canvas.rotate(10);
}
skew
skew隻提供了一種方法
-
- 将畫布在sx
方向上傾斜相應的角度,sx傾斜角度的x
值tan
-
- 将畫布在sy
軸方向上傾斜相應的角度,sy為傾斜角度的y
值tan
// 将坐标系原點移動到畫布正中心
canvas.translate(mWidth / 2, mHeight / 2);
RectF rect = new RectF(0,0,200,200); // 矩形區域
mPaint.setColor(Color.BLACK); // 繪制黑色矩形
canvas.drawRect(rect,mPaint);
canvas.skew(1,0); // 水準錯切 <- 45度
mPaint.setColor(Color.BLUE); // 繪制藍色矩形
canvas.drawRect(rect,mPaint);
save和restore
我的了解,類似于iOS的
CGContextSaveGState
和
CGContextRestoreGState
相關API | 簡介 |
---|---|
save | 把目前的畫布的狀态進行儲存,然後放入特定的棧中 |
saveLayerXxx | 建立一個圖層,并放入特定的棧中 |
restore | 把棧中最頂層的畫布狀态取出來,并按照這個狀态恢複目前的畫布 |
restoreToCount | 彈出指定位置及其以上所有的狀态,并按照指定位置的狀态進行恢複 |
getSaveCount | 擷取棧中内容的數量(即儲存次數) |
狀态棧
狀态棧可以存儲畫布狀态和圖層狀态
save
save 有兩種方法:
// 儲存全部狀态
public int save ()
// 根據saveFlags參數儲存一部分狀态
public int save (int saveFlags)
可以看到第二種方法比第一種多了一個saveFlags參數,使用這個參數可以隻儲存一部分狀态,更加靈活。
saveFlags
參數,參見下表
名稱 | 簡介 |
---|---|
ALL_SAVE_FLAG | 預設,儲存全部狀态 |
CLIP_SAVE_FLAG | 儲存剪輯區 |
CLIP_TO_LAYER_SAVE_FLAG | 剪裁區作為圖層儲存 |
FULL_COLOR_LAYER_SAVE_FLAG | 儲存圖層的全部色彩通道 |
HAS_ALPHA_LAYER_SAVE_FLAG | 儲存圖層的alpha(不透明度)通道 |
MATRIX_SAVE_FLAG | 儲存Matrix資訊( translate, rotate, scale, skew) |
常用格式
save(); //儲存狀态
... //具體操作
restore(); //復原到之前的狀态