Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> android Path 和 PathMeasure 進階

android Path 和 PathMeasure 進階

編輯:關於Android編程

1 概述

在前面的《路徑和文字》中,講解了path的基本用法,這裡講解一些上篇沒有講到的東西。

2 Path

這裡講解path相關的方法,後面繼續講解PathMeasure,以及實例

(1) offset

public void offset(float dx, float dy)
public void offset(float dx, float dy, Path dst)

這裡兩個方法都是指定offset,使得path偏移。其中第二個方法中的dst代表了移動後的path寫入的目標。如果為null,則會寫入調用該方法的path中。

這裡寫圖片描述
 <喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPtXiwO/KudPDwcu12tK7uPa3vbeoo6y0+sLryOfPwjwvcD4NCjxwcmUgY2xhc3M9"brush:java;"> Path path = new Path(); path.moveTo(0, 0); path.lineTo(200, 200); canvas.drawPath(path, paint); path.offset(500, 0); canvas.drawPath(path, paint);

再看看第二個方法的用法:

這裡寫圖片描述

代碼如下

Path path = new Path();
path.moveTo(0, 0);
path.lineTo(200, 200);
canvas.drawPath(path, paint);

Path path1 = new Path();
path1.moveTo(0, 0);
path1.lineTo(100, 100);
path1.offset(500, 0, path);
canvas.drawPath(path, paint);

看這兩句代碼

path1.offset(500, 0, path);
canvas.drawPath(path, paint);

可以看出,偏移後的路徑被寫入了path中。

(2) FillType

FillType,有點類似前面講解的xfermode,不過這裡比較簡單,只有有四個值,如下:

WINDING//默認值,取兩個圖形相交
EVEN_ODD//取不相交的部分
INVERSE_WINDING//反轉相交
INVERSE_EVEN_ODD//反轉不相交部分

來看看實驗的代碼:

Path path = new Path();
path.addRect(100, 100, 500, 500, Path.Direction.CW);
path.addCircle(500, 500, 300, Path.Direction.CW);
path.setFillType(Path.FillType.WINDING);
canvas.drawPath(path, paint);

這裡使用的默認的WINDING,來看看各種FillType對應的圖形:

WINDING

這裡寫圖片描述

EVEN_ODD

這裡寫圖片描述

INVERSE_WINDING

這裡寫圖片描述

INVERSE_EVEN_ODD

這裡寫圖片描述

看了上面的圖片,四種模式基本就清晰了。

(3) reset

reset放在FillType後面講解,就是因為它和reset有關系,reset會清空path的所有數據,但是不會清空FillType。我們用一段代碼來證實:

paint.setColor(Color.BLUE);
Path path = new Path();
path.addRect(100, 100, 500, 500, Path.Direction.CW);
path.addCircle(500, 500, 300, Path.Direction.CW);
path.setFillType(Path.FillType.INVERSE_WINDING);
path.reset();
canvas.drawPath(path, paint);

看上面的代碼,如果FillType被清除,那麼這裡繪制的將是一個空的內容,整個界面將是白色的,然而圖片如下:

這裡寫圖片描述

這裡可以看到,並不是白色,而是藍色,因為這裡的FillType設置的是INVERSE_WINDING,也就是反轉,由於它沒有被清除掉,那麼空路徑的補集就是全集,所以整個屏幕被繪制為藍色。

(4) rewind

rewind和reset類似,但是rewind會清除掉FillType以及所有的直線,曲線,點的數據等,但是他會保留數據結構,這樣可以快速重用,提高一定的性能,例如說,重復繪制一類線段,他們的點的數量都相等,那麼使用rewind可以保留裝載點數據的數據結構,效率會更高。

我們來驗證它是否會清除FillType

paint.setColor(Color.BLUE);
Path path = new Path();
path.addRect(100, 100, 500, 500, Path.Direction.CW);
path.addCircle(500, 500, 300, Path.Direction.CW);
path.setFillType(Path.FillType.INVERSE_WINDING);
path.rewind();
canvas.drawPath(path, paint);

效果如下

這裡寫圖片描述

可以看出,所有數據包括FillType都被清除了。

3 PathMeasure

PathMeasure主要用來測量path,通過它,我們可以得到路徑上特定的點的坐標等等。先看看他的基本方法。

(1) 構造方法

public PathMeasure()
public PathMeasure(Path path, boolean forceClosed)

如上,有兩個方法,第一個就不講解了,第二個方法中有兩個參數;

path:需要測量的path
forceClosed:是否關閉path

(2) setPath

public void setPath(Path path, boolean forceClosed)

這裡就是指定需要測量的path,基本和上面的第二個構造函數類似。

(3) getLength

返回當前path的總長度。

這裡寫圖片描述

代碼如下:

path.addRect(100, 100, 500, 500, Path.Direction.CW);
canvas.drawPath(path, paint);
paint.setStyle(Paint.Style.FILL);
PathMeasure pathMeasure = new PathMeasure(path, false);
float length = pathMeasure.getLength();
canvas.drawText(String.valueOf(length), 500, 500, paint);

可以看到,這裡繪制的1600就是這個path輪廓的長度。

(4) getPosTan

public boolean getPosTan(float distance, float pos[], float tan[])

返回值是boolean,如過path為空,則返回false
傳入參數有三個:
distance:傳入距離起點的距離。
pos[]:意思是position,分別對應點的x,y坐標
tan[]:這個值比較難以理解。我們下面講解下這個值的意義。

先來看一個動圖:

這裡寫圖片描述

代碼如下:

private float[] pos;
private float[] tan;
//繪制動畫路徑
canvas.drawPath(animPath, paint);

if(distance < pathLength){
//獲取位置和
pathMeasure.getPosTan(distance, pos, tan);

matrix.reset();
//計算方位角
float degrees = (float)(Math.atan2(tan[1], tan[0])*180.0/Math.PI);
//計算變換矩陣,用於按照方位角旋轉移動的那個圖像(矩陣後面有篇幅講解,這裡先不管)
matrix.postRotate(degrees, bm_offsetX, bm_offsetY);
matrix.postTranslate(pos[0]-bm_offsetX, pos[1]-bm_offsetY);

//按照矩陣(包括了旋轉和位移)繪制圖像
canvas.drawBitmap(bm, matrix, null);

distance += step;
}else{
distance = 0;
}

invalidate();

從上面的圖中可以看到,移動的圖形,不僅僅只是移動,還進行了旋轉,那麼這個旋轉的角度如何得來,這裡就靠這句代碼

pathMeasure.getPosTan(distance, pos, tan);

裡面的tan就是計算旋轉方位角的關鍵。那麼這個tan代表的意義何在呢,我們知道,移動圖形最開始的時候的x坐標系是和cavans的平行的,在後面的移動中,這個黑色的火焰進入了一個斜線,然後他發生的旋轉,此時,他的x坐標系不再平行於canvas坐標系。這裡看一張圖:

這裡寫圖片描述

圖中紅色的線代表了黑色火焰的x軸,可以看到,他原本是平行於canvas的x軸的,後來在進入第二個斜邊的時候,他沿著藍色箭頭旋轉了,此時紅線不再平行於canvas的x軸,紅線和單位圓的交點的x,y坐標就是這裡返回的tan值。通過這張圖片這裡的意義已經非常清晰了。

(5) getMatrix

public boolean getMatrix(float distance, Matrix matrix, int flags)

這個方法和上面的其實類似,只是他返回的是一個處理好的matrix,但是這個matrix是以左上角作為旋轉點,所以需要將這個點移動到中心點。
其中還多了一個參數flags,指的是這個martrix需要什麼信息。flags的值有如下兩個
PathMeasure.POSITION_MATRIX_FLAG:位置信息
pathMeasure.TANGENT_MATRIX_FLAG:切邊信息,方位角信息,使得圖片按path旋轉。

代碼如下:

matrix.reset();
pathMeasure.getMatrix(distance, matrix, PathMeasure.POSITION_MATRIX_FLAG | pathMeasure.TANGENT_MATRIX_FLAG);
matrix.preTranslate(-bm_offsetX, -bm_offsetY);
canvas.drawBitmap(bm, matrix, null);

其他的相同就不貼了,這裡主要是需要做一個旋轉點的變換:

matrix.preTranslate(-bm_offsetX, -bm_offsetY);

(6) getSegment

public boolean getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo)

這個方法返回boolean,如果截取的長度為0則返回false,否則為true。參數意義如下

startD:起始距離
stopD:終點距離
dst:接收截取的path
startWithMoveTo:是否把截取的path,moveto到起始點。

來看一個例子:

這裡寫圖片描述

代碼如下

path.addRect(300, 300, 700, 700, Path.Direction.CW);
canvas.drawPath(path, paint);
PathMeasure pathMeasure = new PathMeasure(path, false);

Path dstPath = new Path();
pathMeasure.getSegment(0, 800, dstPath, false);
paint.setColor(Color.RED);
canvas.drawPath(dstPath, paint);

可以看到,由於這裡的startWithMoveTo參數設置的是false,那麼截取的path就沒有moveTo到起始位置,則默認moveTo到(0,0)所以導致了繪制的紅線從原點開始。設置了ture之後,圖片如下:

這裡寫圖片描述

可以看到重合了。

好了,Path和PathMeasure就到這裡,上面的例子大家可以多多參考。

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved