Android繪圖之Canvas變換(6)

Android 繪圖學(xué)習(xí)

1 Canvas 與屏幕

前面講解了Canvas的基本概念,Android繪圖之Canvas概念理解(5)
對Canvas的概念進(jìn)行了分析,但是沒有說明和屏幕的關(guān)系,Canvas不等于屏幕,屏幕不會動的,我們也無法對屏幕進(jìn)行(平移,縮放等)操作,只能對Canvas進(jìn)行操作,所以對Canvas進(jìn)行操作,屏幕不動,最終會導(dǎo)致看到的圖像不同。

下面開始講解Canvas的變幻操作:
包括:translate,rotate,scale,skew,clip,clipout,matrix

2 translate 平移

先從最簡單的平移開始:

/**
 * Preconcat the current matrix with the specified translation
 *
 * @param dx The distance to translate in X
 * @param dy The distance to translate in Y
*/
public void translate(float dx, float dy) {
    if (dx == 0.0f && dy == 0.0f) return;
    nTranslate(mNativeCanvasWrapper, dx, dy);
}

對Canvas進(jìn)行平移,
dx: x軸方向進(jìn)行平移,正值向屏幕右側(cè)
dy:y軸方向進(jìn)行平移,正值向屏幕下方

mPaint1.setStrokeWidth(50);
canvas.drawPoint(0,0,mPaint1);
mPaint1.setColor(Color.RED);
canvas.translate(300,300);
canvas.drawPoint(0,0,mPaint1);

繪制兩個點(diǎn)查看原點(diǎn)位置。


//繪制矩形:
canvas.drawRect(200,200,700,700,mPaint1);
mPaint1.setColor(Color.RED);
canvas.translate(200,200);
canvas.drawPoint(0,0,mPaint1);
canvas.drawRect(200,200,700,700,mPaint1);

mPaint1.setColor(Color.GRAY);
canvas.drawRect(300,300,800,800,mPaint1);

原點(diǎn)顯然改變了,以后再繪制任何形狀都是以translate后的原點(diǎn)開始繪制。

3 scale 縮放

/**
 * Preconcat the current matrix with the specified scale.
 *
 * @param sx The amount to scale in X
 * @param sy The amount to scale in Y
 */
public void scale(float sx, float sy) {
    if (sx == 1.0f && sy == 1.0f) return;
    nScale(mNativeCanvasWrapper, sx, sy);
}

/**
 * Preconcat the current matrix with the specified scale.
 *
 * @param sx The amount to scale in X
 * @param sy The amount to scale in Y
 * @param px The x-coord for the pivot point (unchanged by the scale)
 * @param py The y-coord for the pivot point (unchanged by the scale)
 */
public final void scale(float sx, float sy, float px, float py) {
    if (sx == 1.0f && sy == 1.0f) return;
    translate(px, py);
    scale(sx, sy);
    translate(-px, -py);
}

參數(shù)說明
sx:橫向的縮放,默認(rèn)為1,小數(shù)縮小,整數(shù)放大
sy:縱向的縮放,默認(rèn)為1,小數(shù)縮小,整數(shù)放大

px,py,看源碼知道是先translate,執(zhí)行sx,sy然后再translate反方向。
第二次translate的坐標(biāo)為(-pxsx,-pxsy),最終的效果就是px,py是縮放后不動的點(diǎn)。

canvas.drawRect(200,200,700,700,mPaint1);
canvas.scale(0.5f,0.5f);
mPaint1.setColor(Color.GRAY);
canvas.drawRect(200,200,700,700,mPaint1);

縮放后坐標(biāo)減半。

如果想控制縮放后的位置,如何控制呢,這就需要第二個函數(shù)。

canvas.drawRect(200,200,700,700,mPaint1);
canvas.scale(0.5f,0.5f,200,200);
mPaint1.setColor(Color.GRAY);
canvas.drawRect(200,200,700,700,mPaint1);

還可以控制其他位置,例如控制縮放后在中心。

canvas.drawRect(200,200,700,700,mPaint1);
canvas.scale(0.5f,0.5f,450,450);
mPaint1.setColor(Color.GRAY);
canvas.drawRect(200,200,700,700,mPaint1);

4 Canvas 的旋轉(zhuǎn)rotate

/**
 * Preconcat the current matrix with the specified rotation.
 *
 * @param degrees The amount to rotate, in degrees
 */
public void rotate(float degrees) ;
/** *
 * @param degrees The amount to rotate, in degrees
 * @param px The x-coord for the pivot point (unchanged by the rotation)
 * @param py The y-coord for the pivot point (unchanged by the rotation)
 */
public final void rotate(float degrees, float px, float py) {
    if (degrees == 0.0f) return;
    translate(px, py);
    rotate(degrees);
    translate(-px, -py);
}

rotate有兩個函數(shù):
rotate(float degrees)
rotate(float degrees, float px, float py)
Degree:旋轉(zhuǎn)的角度,正值為順時針,負(fù)值為逆時針
Px,py:旋轉(zhuǎn)的中心,如果不指定旋轉(zhuǎn)中心默認(rèn)為(0,0)點(diǎn)

canvas.drawRect(400,400,900,900,mPaint1);
canvas.rotate(-10);
mPaint1.setColor(Color.GRAY);
canvas.drawRect(400,400,900,900,mPaint1);

指定旋轉(zhuǎn)中心為矩形中心

canvas.drawRect(400,400,900,900,mPaint1);
canvas.drawPoint(100,100,mPaint1);
canvas.rotate(10,650,650);

mPaint1.setColor(Color.GRAY);
canvas.drawRect(400,400,900,900,mPaint1);

5 Skew 傾斜 畫布

/**
 * Preconcat the current matrix with the specified skew.
 *
 * @param sx The amount to skew in X
 * @param sy The amount to skew in Y
 */
public void skew(float sx, float sy) {
    if (sx == 0.0f && sy == 0.0f) return;
    nSkew(mNativeCanvasWrapper, sx, sy);
}

參數(shù)說明:
sx:畫布在x方向上傾斜相應(yīng)的角度,sx傾斜角度的tan值,
sy:畫布在y軸方向上傾斜相應(yīng)的角度,sy為傾斜角度的tan值,

canvas.drawRect(200,200,700,700,mPaint1);
canvas.save();
canvas.skew(tan(30),0);
mPaint1.setColor(Color.GRAY);
canvas.drawRect(200,200,700,700,mPaint1);
canvas.restore();
mPaint1.setColor(Color.BLUE);
canvas.drawRect(200,800,700,1300,mPaint1);
canvas.save();
canvas.skew(0,tan(30));
mPaint1.setColor(Color.GRAY);
canvas.drawRect(200,800,700,1300,mPaint1);
canvas.restore();

public float tan(int degree){
   return (float) Math.tan(degree*1.0/180*Math.PI);
}

6 clip 切割畫布

根據(jù)矩形或者路徑裁剪畫布,畫布被切割之后,只有部分區(qū)域可用,其他區(qū)域無法繪制內(nèi)容。
Clip函數(shù)切割的區(qū)域可用,clipOut未被切割的區(qū)域可用。(過時函數(shù)不再講解)

clipRect(@NonNull RectF rect)
clipRect(@NonNull Rect rect)
clipRect(float left, float top, float right, float bottom)
clipRect(int left, int top, int right, int bottom)

clipPath(@NonNull Path path)

一下函數(shù)需要api26以上
clipOutRect(@NonNull RectF rect)
clipOutRect(@NonNull Rect rect)
clipOutRect(float left, float top, float right, float bottom)
clipOutRect(int left, int top, int right, int bottom)
clipOutPath(@NonNull Path path)

canvas.drawRect(200,200,700,700,mPaint1);
mPaint1.setColor(Color.GRAY);
canvas.drawRect(200,800,700,1300,mPaint1);
canvas.clipRect(200, 200, 700, 700);//截取畫布大小為
canvas.drawCircle(100,100,100,mPaint1);//畫布被剪切,無法畫上
canvas.drawCircle(300,300,100,mPaint1);//可以畫上
canvas.drawRect(200,200,700,700,mPaint1);
mPaint1.setColor(Color.GRAY);
canvas.drawRect(200,800,700,1300,mPaint1);
canvas.clipOutRect(200, 200, 700, 700);//截取畫布大小為
canvas.drawCircle(100,100,100,mPaint1);//可以畫上
canvas.drawCircle(300,300,100,mPaint1);//無法畫上

7 matrix 變換

Matrix提供了一些方法來控制變換:

setTranslate(float dx,float dy):平移操作
setSkew(float kx,float ky):skew操作
setSkew(float kx,float ky,float px,float py):
setRotate(float degrees):旋轉(zhuǎn)
setRotate(float degrees,float px,float py):
setScale(float sx,float sy):縮放
setScale(float sx,float sy,float px,float py):

Matrix的pre XXX和postXXX是左乘右乘的區(qū)別,是為了組合各種操作,因?yàn)榫仃嚥环辖粨Q率,所以左乘右乘效果不同,一般利用matrix的效果需要反著乘得到最終的matrix.
以上的效果和canvas的set操作效果一樣。

canvas.drawRect(200,200,700,700,mPaint1);
mPaint1.setColor(Color.GRAY);
Matrix matrix = new Matrix();
matrix.setRotate(10);
canvas.setMatrix(matrix);
canvas.drawRect(200,200,700,700,mPaint1);

android繪圖之Paint(1)
android繪圖之Canvas基礎(chǔ)(2)
Android繪圖之Path(3)
Android繪圖之drawText繪制文本相關(guān)(4)
Android繪圖之Canvas概念理解(5)
Android繪圖之Canvas變換(6)
Android繪圖之Canvas狀態(tài)保存和恢復(fù)(7)
Android繪圖之PathEffect (8)
Android繪圖之LinearGradient線性漸變(9)
Android繪圖之SweepGradient(10)
Android繪圖之RadialGradient 放射漸變(11)
Android繪制之BitmapShader(12)
Android繪圖之ComposeShader,PorterDuff.mode及Xfermode(13)
Android繪圖之drawText,getTextBounds,measureText,FontMetrics,基線(14)
Android繪圖之貝塞爾曲線簡介(15)
Android繪圖之PathMeasure(16)
Android 動態(tài)修改漸變 GradientDrawable

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容