1. 程式人生 > >Android 繪圖基礎:Path(繪製三角形、貝塞爾曲線、正餘弦)

Android 繪圖基礎:Path(繪製三角形、貝塞爾曲線、正餘弦)

學習重點:
理解path的使用
理解貝塞爾曲線的繪製原理
可動正餘弦的繪製

Path的簡單介紹

  在 Android 繪圖基礎:Canvas畫布——自定義View(繪製錶盤、矩形、圓形、弧、漸變) 中我們可以看到Canvas的強大功能,其實Canvas還有一種繪圖方式就是drawpath(),沒有在上篇部落格中寫出這個方法就是想進行單獨的介紹。我們通過Canvas 的其他方法只能繪製特定的圖形,但是等我們學會了Path,我們就能夠繪製任何圖形了!
  Path是Android為我們提供的非常有用的類,它可以預先在View上將N個點連成一條“路徑”,然後呼叫Canvas.drawpath方法就可沿著路徑繪製圖形了。
  

繪製三角形

既然我們要使用Path當然要先定義一個Path

  private Path mpath;

onDraw方法中繪製

        //mpathd的起始位置
        mpath.moveTo(100, 100);
        //從起始位置劃線到(200, 200)座標
        mpath.lineTo(200, 200);
        //將mpath封閉,也可以寫 mpath.lineTo(100, 100);代替
        mpath.close();
        //繪製path路徑
        canvas.drawPath(mpath, Paintpath);

貝塞爾曲線

設麼是貝塞爾曲線,簡單的說就是通過三個點,不斷地取三點連線的中點,最後近似出一條光滑的曲線。
這裡寫圖片描述

//貝塞爾曲線需要三個點(起始點 控制點 結束點)來確定
       //貝塞爾曲線的起始點
    mpath.moveTo(300, 300);
    //繪製貝塞爾曲線需要我們呼叫quadTo方法
    //控制點
        mpath.quadTo(50, 450, 300, 500);
        //結束點
        canvas.drawPath(mpath, Paintpath);
        //繪製
canvas.drawPath(mpath, Paintpath);
//如果為了更清楚的看出貝塞爾曲線與點的關係,可以通過drawpoint將點畫出

正餘弦曲線

在貝塞爾曲線的基礎上我們再來理解正餘弦,正餘弦的繪製需要理解座標點。繪製正餘弦曲線我們需要使用rQuadTo()它的座標都是相對的。

//其實位置
mpath.moveTo(100, 100);
//rQuardto的位置是相對的
mpath.rQuadTo(20, 20, 40, 0);
mpath.rQuadTo(20, -20, 40, 0);  

這裡寫圖片描述
注:這裡要著重理解rQuardto的位置是相對的,像上圖所示,相信看了上面的圖你就會很好地理解了。

可動正餘弦

思路:通過改變繪製的初始位置進行改變,相當於向一邊拖拽
這裡寫圖片描述

public class MyPathView extends View{
    private int width;
    private int height;

    private Paint Paintpath;
    private Path mpath;
    private Paint PaintText;
    private Paint Paintpoint;
    private int count;
    private int size;
    private Handler mhanHandler=new Handler(){
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
            case 0x23:
                count++;
    //count至少80,根據我們畫的mpath.rQuadTo()確定
            if(count>=80){
                count=0;        
            }
            size++;
            if(size>10){
                size=5;
            }
            mhanHandler.sendEmptyMessageDelayed(0x23, 200);
            //重新繪製
                invalidate();
                break;

            default:
                break;
            }

        };
    };

    public MyPathView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
    }
    public MyPathView(Context context, AttributeSet attrs) {
        super(context, attrs);
        Paintpath=new Paint();
        Paintpath.setColor(Color.BLACK);
        Paintpath.setAntiAlias(true);
    //  Paintpath.setStrokeWidth(5);
        Paintpath.setStyle(Style.STROKE);


        PaintText=new Paint();
        PaintText.setColor(Color.BLACK);
        PaintText.setAntiAlias(true);       
        PaintText.setTextSize(40);

        mpath=new Path();
        Paintpoint=new Paint();
        Paintpoint.setColor(Color.RED);
    //  Paintpoint.setStrokeWidth(20);
        Paintpoint.setStyle(Style.STROKE);
        mhanHandler.sendEmptyMessage(0x23);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mpath.reset();
        //通過不斷修改count值,讓曲線動起來
        mpath.moveTo(count, 100);

        for(int i=0;i<20;i++){
            //rQuadTo
            mpath.rQuadTo(20, size, 40, 0);
            mpath.rQuadTo(20, -size, 40, 0);    
        }       
        canvas.drawPath(mpath, Paintpath);
        canvas.drawCircle(200, 100, 50, Paintpoint);

    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
        height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec);
    }
}