1. 程式人生 > >自定義View-座標轉換

自定義View-座標轉換

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

1)平移:

public void translate(float dx,float dy)
座標平移,在當前原點的基礎上水平移動 dx 個距離,垂直移動 dy 個距離,正負符號決定方向。座標原點改變後,所有的座標都是以新的原點為參照進行定位。下面兩段程式碼是等效的:
程式碼段 1:
canvas.drawPoint(10, 10, paint); 

程式碼段 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();
    }
}

結果: