Android_2D繪圖的學習Paint,Canvas(三)

前言

上一節,學習了Paint的高級用法後,這一節我們將canvas的用法。主要涉及到canvas的繪製座標變換translate,rotate。還沒看過上一節的請點擊這裏:Android_2D繪圖的學習Paint,Canvas(二)

一,translate

translate在很多語言的圖像處理中都存在,意思是平移,在canvas中,他表示平移座標原點。比如說,你要在一個View的中心點畫一個半徑爲r圓。你可以這樣直接畫:canvas.drawCircle(getWidth()/2,getHeight()/2,r,paint);也可以使用translate,先移動畫布的座標原點爲view的中心:canvas.trandlate(getWidth()/2,getHeight()/2);然後再根據新的座標畫出圓即可:canvas.drawCircle(0,0,r,paint);這裏起始點(0,0)就是view的中心。

二,rotate

rotate是旋轉的意思,在canvas中,大家都說是旋轉畫布,其實更好理解的應該是旋轉座標。比如說,你先畫一個圖形,然後調用rotate方法,將會看到我們的圖像沒有被旋轉。
這裏我做了一個測試,先畫一個藍色的矩形,然後將畫布rotate 30°,再畫一個紅色的矩形,根據上面的原理,應該是紅色的被旋轉了,而藍色的則沒有被旋轉。那麼事實呢,請看下圖:
1
代碼:

        //移動座標原點爲View中心
        canvas.translate(getWidth()/2, getHeight()/2);
        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Style.STROKE);
        //先畫藍色矩形
        canvas.drawRect(20, 0, 150, 100, mPaint);
        //旋轉畫布
        canvas.rotate(30);
        //再畫紅色矩形
        mPaint.setColor(Color.RED);
        canvas.drawRect(20, 0, 150, 100, mPaint);

我們看到正如我們說的一樣,rotate只是旋轉了畫布的座標。

三,save,restroe

save:用來保存Canvas的狀態。save之後,可以調用Canvas的平移、放縮、旋轉、錯切、裁剪等操作。
restore:用來恢復Canvas之前保存的狀態。防止save後對Canvas執行的操作對後續的繪製有影響。
這裏畫兩個矩形來講解使用方法,我們先繪製一個矩形,然後保存當前canvas座標值,再旋轉45度,畫出一個同樣的矩形,爲了區分,顏色不一樣,然後恢復canvas的座標值,繪出x,y座標。
效果:
1
代碼:

// 矩形寬度
        int lenght = dp2px(120);
        canvas.translate(getWidth() / 2, getHeight() / 2);
        // 第一個黑色矩形
        canvas.drawRect(-lenght, -lenght, lenght, lenght, mPaint);
        // 保存x軸方向爲3點鐘方向的座標
        canvas.save();
        // 旋轉座標軸
        canvas.rotate(45);
        mPaint.setColor(Color.BLUE);
        // 第二個藍色矩形
        canvas.drawRect(-lenght, -lenght, lenght, lenght, mPaint);
        // 恢復座標軸
        canvas.restore();
        mPaint.setColor(Color.RED);
        // 繪製座標軸
        canvas.drawLine(0, 0, 300, 0, mPaint);
        canvas.drawText("x", 330, 0, textPaint);
        canvas.drawLine(0, 0, 0, 300, mPaint);
        canvas.drawText("y", 0, 330, textPaint);

這裏當然save和restore是成對出現的,不然缺少意義,當然restore調用次數要少於save的調用次數。

四,簡單的錶盤

學會了translate,rotate,save,restore後,我們實踐一下,繪製一個像這樣的錶盤:
1
看過這個簡單錶盤,都是由線,三角形,圓,文字繪出的,這些在前面都已經講過,思路都在代碼裏,直接上代碼:

    @Override
    protected void onDraw(Canvas canvas) {

        // 半徑
        int radius = dp2px(100);
        // 修改座標軸原點
        canvas.translate(getWidth() / 2, getHeight() / 2);
        // 保存座標軸的狀態
        canvas.save();
        // 畫一個圓
        canvas.drawCircle(0, 0, radius, mPaint);
        // 逆時針旋轉60度,這樣 1 刻度就能在正確的位置
        canvas.rotate(-60);
        // 畫出刻度:一共有60個刻度,從第一個刻度開始,每5個刻度爲長刻度
        for (int i = 0; i < 60; i++) {
            if (i % 5 == 0) {
                // 繪製長刻度
                canvas.drawLine(radius, 0, radius + dp2px(20), 0, mPaint);
                /* 繪製數字,因爲方向的問題,所以這裏還需要旋轉平移座標軸 */
                // 保存-60的座標軸
                canvas.save();
                // 將座標軸移動到該畫數字的位置
                canvas.translate(radius + dp2px(25), 0);
                // 旋轉座標,可以讓數字朝向圓心
                canvas.rotate(90);
                String text = String.valueOf(i / 5 + 1);
                // 測量字體的寬度,使其居中
                int width = (int) textPaint.measureText(text);
                canvas.drawText(text, -width / 2, 0, textPaint);
                // 恢復後:座標原點還是在View的中心,x軸方向爲1點鐘方向
                canvas.restore();
            } else {
                // 繪製短刻度
                canvas.drawLine(radius, 0, radius + dp2px(10), 0, mPaint);
            }
            canvas.rotate(360 / 60f);
        }
        // 恢復後:座標原點還是在View的中心,x軸方向爲3點鐘方向
        canvas.restore();
        // 畫出指針
        canvas.drawLine(0, 0, 0, -dp2px(60), mPaint);
        Path path = new Path();
        path.moveTo(3, -dp2px(60));
        path.lineTo(-3, -dp2px(60));
        path.lineTo(0, -dp2px(63));
        path.close();
        canvas.drawPath(path, mPaint);
        // 繪製文字
        String text = "canvas clock";
        int width = (int) textPaint.measureText(text);
        canvas.drawText(text, -width / 2, dp2px(50), textPaint);
    }

主要考慮一下數字方向的繪製,網上很多都沒有考慮到這個問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章