概念
畫布,通過畫筆繪製幾何圖形,文本,路徑和位圖等
常用API類型
常用API分爲3類 :繪製,變換,狀態保存和恢復
第二類: 變換
基本類
ca
public class TransformView extends View {
private Paint mPaint;
public TransformView(Context context) {
this(context, null);
}
public TransformView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public TransformView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
//默認紅色
mPaint.setColor(Color.RED);
mPaint.setStrokeWidth(4);
mPaint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
....
這裏寫操作
}
}
都在onDraw中寫
平移操作
canvas.drawRect(0,0, 400, 400, mPaint);
canvas.translate(50, 50);
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0, 400, 400, mPaint);
canvas.drawLine(0, 0, 600,600, mPaint);
縮放操作
canvas.drawRect(200,200, 700,700, mPaint);
canvas.scale(0.5f, 0.5f);
mPaint.setColor(Color.GRAY);
canvas.drawRect(200,200, 700,700, mPaint);
顯示
修改
修改如下代碼效果如圖:
canvas.drawRect(200,200, 700,700, mPaint);
// canvas.scale(0.5f, 0.5f);
//先translate(px, py),再scale(sx, sy),再反響translate
canvas.scale(0.5f, 0.5f, 200,200);
mPaint.setColor(Color.GRAY);
canvas.drawRect(200,200, 700,700, mPaint);
顯示
//先translate(px, py),再scale(sx, sy),再反響translate
canvas.scale(0.5f, 0.5f, 200,200);
等同於
canvas.translate(200, 200);
canvas.scale(0.5f, 0.5f);
canvas.translate(-200, -200);
旋轉操作
canvas.translate(50,50);
canvas.drawRect(0,0, 700,700, mPaint);
canvas.rotate(45);
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0, 700,700, mPaint);
旋轉中心
canvas.drawRect(400, 400, 900, 900, mPaint);
canvas.rotate(45, 650, 650); //px, py表示旋轉中心的座標
mPaint.setColor(Color.GRAY);
canvas.drawRect(400, 400, 900, 900, mPaint);
傾斜操作
/**
* @params sx 將畫布在x方向上傾斜相應的角度,sx傾斜角度的tan值,其實就是將y逆時針旋轉相應的角度
* @params sy 將畫布在y方向上傾斜相應的角度,sx傾斜角度的tan值,其實就是將x順時針旋轉相應的角度
*
public void skew (float sx, float sy)
canvas.drawRect(0,0, 400, 400, mPaint);
canvas.skew((float) Math.sqrt(3), 0);
mPaint.setColor(Color.GRAY);
canvas.drawRect(0, 0, 400, 400, mPaint);
首先
明確X軸Y軸方向:
代碼中
canvas.skew((float) Math.sqrt(3), 0);
其次
明確參數:
@params sx sx傾斜角度的tan值
@params sy sy傾斜角度的tan值
tan值 三角函數 tanθ =x/y, 這裏的xy 不是sx,sy
常用的有:
tanθ 爲45° 爲1
tanθ 爲60° 爲根號3
tanθ 爲30° 爲3分之根號3
代碼中:
canvas.skew((float) Math.sqrt(3), 0);
sx:
爲(float) Math.sqrt(3) 即 根號3 60°。
意思是y軸逆時針旋轉60度。
sy:不變即x軸不變
如圖:
紅色的爲原先的矩形,灰色爲之後的圖形
再比如:
canvas.drawRect(0,0, 400, 400, mPaint);
canvas.skew((float) Math.sqrt(3)/3, 0);
mPaint.setColor(Color.GRAY);
canvas.drawRect(0, 0, 400, 400, mPaint);
代碼中:
canvas.skew((float) Math.sqrt(3)/3, 0);
sx:
爲(float) Math.sqrt(3) 即 3分之根號3 30°。
意思是y軸逆時針旋轉30度。
sy:不變即x軸不變
同理,反過來
canvas.drawRect(0,0, 400, 400, mPaint);
canvas.skew(0, (float) Math.sqrt(3)/3);
mPaint.setColor(Color.GRAY);
canvas.drawRect(0, 0, 400, 400, mPaint);
代碼中:
canvas.skew(0, (float) Math.sqrt(3)/3);
sx:不變即y軸不變
sy:
爲(float) Math.sqrt(3) 即 3分之根號3 30°。
意思是x軸順時針旋轉30度。
總結:
sx 將畫布在x方向上傾斜相應的角度,sx傾斜角度的tan值,其實就是將y逆時針旋轉相應的角度
sy 將畫布在y方向上傾斜相應的角度,sx傾斜角度的tan值,其實就是將x順時針旋轉相應的角度
切割
裁剪clipRect
canvas.drawRect(200, 200,700, 700, mPaint);
mPaint.setColor(Color.GRAY);
canvas.drawRect(200, 800,700, 1300, mPaint);
canvas.clipRect(200, 200,700, 700); //畫布被裁剪
canvas.drawCircle(100,100, 100,mPaint); //座標超出裁剪區域,無法繪製
canvas.drawCircle(300, 300, 100, mPaint); //座標區域在裁剪範圍內,繪製成功
反向裁剪 :clipOutRect
canvas.drawRect(200, 200,700, 700, mPaint);
mPaint.setColor(Color.GRAY);
canvas.drawRect(200, 800,700, 1300, mPaint);
canvas.clipOutRect(200,200,700,700); //畫布裁剪外的區域
canvas.drawCircle(100,100,100,mPaint); //座標區域在裁剪範圍內,繪製成功
canvas.drawCircle(300, 300, 100, mPaint);//座標超出裁剪區域,無法繪製
矩陣
canvas.drawRect(0,0,700,700, mPaint);
Matrix matrix = new Matrix();
// matrix.setTranslate(50,50);
// matrix.setRotate(45);
matrix.setScale(0.5f, 0.5f);
canvas.setMatrix(matrix);
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0,700,700, mPaint);
第三類 :狀態保存和恢復
Canvas調用了translate,scale,rotate,skew,clipRect等變換後,後續的操作都是基於變換後的Canvas,都會受到影響,對於後續的操作很不方便。Canvas提供了save,saveLayer,saveLayerAlpha,restore,restoreToCount來保存和恢復狀態。
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0,500,500,mPaint);
canvas.translate(50,50);
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0,500,500,mPaint);
畫了兩個矩形
如果我們想在原點再畫一條線。需要如下代碼
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0,500,500,mPaint);
canvas.translate(50,50);
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0,500,500,mPaint);
canvas.translate(-50,-50);
canvas.drawLine(0,0,400,500,mPaint);
我們可以用canvas中的save方法來進行保存,不用
canvas.translate(-50,-50);
平移回來
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0,500,500,mPaint);
//保存狀態
canvas.save();
canvas.translate(50,50);
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0,500,500,mPaint);
//恢復狀態
canvas.restore();
// canvas.translate(-50,-50);
canvas.drawLine(0,0,400,500,mPaint);
也可以達到上圖效果。
如果save()保存了兩次,restore()了一次,只是回到最近一次的save()方法。
如下代碼並沒有在原點繪製,而是在第二次保存的位置繪製。
即 canvas.translate(50,50); 位置繪製。
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0,500,500,mPaint);
canvas.save();
canvas.translate(50,50);
mPaint.setColor(Color.RED);
canvas.drawRect(0,0,500,500,mPaint);
canvas.save();
canvas.translate(50,50);
mPaint.setColor(Color.BLUE);
canvas.drawRect(0,0,500,500,mPaint);
canvas.restore();
canvas.drawLine(0,0,400,500,mPaint);
如圖
調用兩次restore方法:
mPaint.setColor(Color.GRAY);
canvas.drawRect(0,0,500,500,mPaint);
canvas.save();
canvas.translate(50,50);
mPaint.setColor(Color.RED);
canvas.drawRect(0,0,500,500,mPaint);
canvas.save();
canvas.translate(50,50);
mPaint.setColor(Color.BLUE);
canvas.drawRect(0,0,500,500,mPaint);
canvas.restore();
canvas.restore();
// canvas.translate(-50,-50);
canvas.drawLine(0,0,400,500,mPaint);
如圖
canvas.getSaveCount():可以用來查看save的次數。
默認爲1.
通過
int state = canvas.save();
canvas.restoreToCount(state);
可以回到 state 時的狀態
還可以通過layerId和 canvas.restoreToCount(layerId);
來達到重置效果。
/**
* 1.canvas內部對於狀態的保存存放在棧中
* 2.可以多次調用save保存canvas的狀態,並且可以通過getSaveCount方法獲取保存的狀態個數
* 3.可以通過restore方法返回最近一次save前的狀態,也可以通過restoreToCount返回指定save狀態。指定save狀態之後的狀態全部被清除
* 4.saveLayer可以創建新的圖層,之後的繪製都會在這個圖層之上繪製,直到調用restore方法
* 注意:繪製的座標系不能超過圖層的範圍, saveLayerAlpha對圖層增加了透明度信息
*/
canvas.drawRect(200,200, 700,700, mPaint);
//
int layerId = canvas.saveLayer(0,0, 700, 700, mPaint);
mPaint.setColor(Color.GRAY);
Matrix matrix = new Matrix();
matrix.setTranslate(100,100);
canvas.setMatrix(matrix);
canvas.drawRect(0,0,700,700, mPaint); //由於平移操作,導致繪製的矩形超出了圖層的大小,所以繪製不完全
canvas.restoreToCount(layerId);
mPaint.setColor(Color.RED);
canvas.drawRect(0,0,100,100, mPaint);
總結:
- canvas內部對於狀態的保存存放在棧中
- 可以多次調用save保存canvas的狀態,並且可以通過getSaveCount方法獲取保存的狀態個數
- 可以通過restore方法返回最近一次save前的狀態,也可以通過restoreToCount返回指定save狀態。指定save狀態之後的狀態全部被清除
- saveLayer可以創建新的圖層,之後的繪製都會在這個圖層之上繪製,直到調用restore方法,
注意:繪製的座標系不能超過圖層的範圍, saveLayerAlpha對圖層增加了透明度信息