天天看點

自定義View-坐标轉換

坐标轉換

預設情況下,畫布坐标的原點就是繪圖區的左上角,向左為負,向右為正,向上為負,向下為正,但是通過 Canvas ᨀ供的方法可以對坐标進行轉換。轉換的方式主要有 4 種:平移、旋轉、縮放和拉斜:

1)平移:

public void translate(float dx,float dy)
           

坐标平移,在目前原點的基礎上水準移動 dx 個距離,垂直移動 dy 個距離,正負符号決定方向。坐标原點改變後,所有的坐标都是以新的原點為參照進行定位。下面兩段代碼是等效的:

代碼段 1:

代碼段 2:

canvas.translate(10, 10);
canvas.drawPoint(0, 0, paint);
           

2)旋轉:

public void rotate(float degrees)
           

将畫布的坐标以目前原點為中心旋轉指定的角度,如果角度為正,則為順時針旋轉,否則為逆時針旋轉。

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

以點(px, py)為中心對畫布坐标進行旋轉 degrees 度,為正表示順時針,為負表示逆時針。

3)縮放:

public void scale(float sx,float sy)
           

縮放畫布的坐标,sx、sy 分别是 x 方向和 y 方向的縮放比例,小于 1 表示縮小,等于1 表示不變,大于 1 表示放大。畫布縮放後,繪制在畫布上的圖形也會等比例縮放。

縮放的機關是倍數,比如 sx 為 0.5 時,就是在 x 方向縮小 0.5 倍。

public final void scale(float sx,float sy,float px,float py)
           

以(px,py)為中心對畫布進行縮放。

4)拉斜:

public void skew(float sx,float sy)
           

将畫布分别在 x 方向和 y 方向拉斜一定的角度,sx 為 x 方向傾斜角度的 tan 值,sy 為y 方向傾斜角度的 tan 值,比如我們打算在 X 軸方向上傾斜 45 度,則 tan45=1,寫

成:canvas.skew(1, 0)。

坐标轉換後,後面的圖形繪制功能将跟随新坐标,轉換前已經繪制的圖形不會有任何的變化。另外,為了能恢複到坐标變化之前的狀态,Canvas 定義了兩個方法用于儲存現場和恢複現場:

public int save ()
           

儲存現場。

public void restore ()
           

恢複現場到 save()執行之前的狀态。

MainActivity:

public class CoordinateView extends View {
    public CoordinateView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.RED);
        paint.setStrokeWidth(2);//設定邊的寬度
        paint.setStyle(Paint.Style.STROKE);//設定畫筆的樣式為描邊
        //儲存現場
        canvas.save();
        for (int i = 0; i < 5; i++) {
            canvas.drawRect(0, 0, 150, 150, paint);
            canvas.translate(30, 30);
        }
        //恢複現場
        canvas.restore();//恢複現場到 save()執行之前的狀态。
        //平移坐标,讓接下來的圖形繪制在上一次圖形的下面
        canvas.translate(0, 300);
        canvas.save();
        for (int i = 0; i < 5; i++) {
            canvas.drawRect(0, 0, 400, 400, paint);
            canvas.scale(0.9f, 0.9f, 200, 200);
        }
        canvas.restore();//恢複現場到 save()執行之前的狀态。 也就是在矩形的下面
        //平移坐标,讓接下來的圖形繪制在上一次圖形的下面
        canvas.translate(0, 450);
        canvas.save();
        canvas.drawCircle(200, 200, 200, paint);
        for (int i = 0; i < 12; i++) {
            canvas.drawLine(350, 200, 400, 200, paint);
            canvas.rotate(30, 200, 200);
        }
        canvas.restore();
    }
}
           

結果:

自定義View-坐标轉換