關(guān)于Path之前寫的也很多了,例如path繪制線,path繪制一階,二階和三階貝塞爾路徑,這些都是path的基本用法。今天我要帶大家看的是Path 的高級用法,先上圖,再吹。
創(chuàng)新互聯(lián)公司從2013年創(chuàng)立,公司以成都做網(wǎng)站、成都網(wǎng)站制作、系統(tǒng)開發(fā)、網(wǎng)絡(luò)推廣、文化傳媒、企業(yè)宣傳、平面廣告設(shè)計等為主要業(yè)務(wù),適用行業(yè)近百種。服務(wù)企業(yè)客戶上千余家,涉及國內(nèi)多個省份客戶。擁有多年網(wǎng)站建設(shè)開發(fā)經(jīng)驗。為企業(yè)提供專業(yè)的網(wǎng)站建設(shè)、創(chuàng)意設(shè)計、宣傳推廣等服務(wù)。 通過專業(yè)的設(shè)計、獨特的風(fēng)格,為不同客戶提供各種風(fēng)格的特色服務(wù)。
效果大致是這樣的??粗遣皇峭谩T挷欢嗾f,切入正題:
既然今天要談Path的高級用法,那就先來講一講(Path -- 中文 )就是“路徑”既然是路徑,從我們面向?qū)ο蟮南敕ǖ脑?,我們就容易想?路徑 的長度,路徑的某一點等。想到這里我們就引出今天 的主要 類--------PathMeasure,字面意思很容易理解--翻譯成 路徑測量。對這就是我們用來測量路徑的類。既然是一個類,我們就要看他集體有哪些方法和屬性。
1.構(gòu)造方法:
一個是有參數(shù),一個無參數(shù)。
無參數(shù)就很容易理解就是直接創(chuàng)建對象,那有參數(shù)呢?
PathMeasure(Path path, boolean forceClosed) ;
第一個參數(shù) Path 咿 !這不就是我們的Path 了嗎。對既然是測量類,那就是要確定需要測量的那個路徑,那第二個參數(shù)呢?
第二個參數(shù)是用來確保 Path 閉合,如果設(shè)置為 true, 則不論之前Path是否閉合,都會自動閉合該 Path(如果Path可以閉合的話)。
2.方法:
這方法還挺多,都是干啥的呢?就找?guī)讉€重要的,常用的講講:
第一個那就是 setPath(Path path, boolean forceClosed)
這方法一看就知道設(shè)置path 路徑的,就是如果我們創(chuàng)建 PathMeasure,時用的是無參的構(gòu)造方法時 ,這時候就要用此方法,告訴PathMeasure 當(dāng)前需要測量的是哪一個path路徑。(個人喜歡用無參,比較靈活)。
第二個那就是getLength(),很容易理解就是 獲得 path 的總長度。
第三個:getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo),這個方法非常重要,截取片段,截取的結(jié)果就是,我們的path路徑。參數(shù)也很好理解。第一個是開始的距離,第二個是結(jié)束的距離(相對于起點==既然是起點,我們怎么找他們的起點呢,其實就是我們繪制圖畫筆開始的哪一點)。第三個參數(shù)就是返回的路徑。第四個參數(shù)起始點是否使用 moveTo 用于保證截取的 Path 第一個點位置不變。
第四個:getPosTan(float distance, float[] pos, float[] tan),這個也是非常重要的,為什么呢?聽我解釋一下他的參數(shù)就知道了。第一個參數(shù)是距離(相對于繪制起點的路徑距離),第二個參數(shù)是距離起點的坐標(biāo)點,第三個參數(shù)返回的是正玄函數(shù)tan@角度。
對這些參數(shù)了解之后下面就來講解我們今天的例子:
首先我們先來個簡單的:例如
如圖這樣的分析過程:
1.首先繪制一個圓(藍(lán)色的),從45度開始繪制,注意圓的起點。
2.同圓心繪制大圓(輔助圓)用來輔助繪制藍(lán)色的線。
3.通過getPosTan(float distance, float[] pos, float[] tan)方法得到兩個圓的終點的坐標(biāo)。
4.利用lineTo(x,y)繪制線。就得到我們的搜索圖形了。
5.接下來就是實時 截取片段。getSegment(float startD, float stopD, Path dst, boolean startWithMoveTo),截取從距離0到getlength();這樣就產(chǎn)生了一個動態(tài)的效果了。
看代碼:
關(guān)于畫筆,canvas畫布,valueanimator動畫,這些請看之前的博客,都有詳細(xì)講解。
public class MySearch extends View { Paint paint; Path searchPath; //搜索的圓 Path ciclePath; //外圓 //獲得寬高 int w; int h; //這是保存截取時,返回的坐標(biāo)點 float serpos[]; float cicpos[]; //測量 path 的類 PathMeasure measure; //動畫產(chǎn)生的實時數(shù)據(jù) float value; public MySearch(Context context) { this(context,null); } public MySearch(Context context, @Nullable AttributeSet attrs) { this(context,attrs,0); } public MySearch(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //獲得屏幕的寬高 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); w = wm.getDefaultDisplay().getWidth(); h = wm.getDefaultDisplay().getHeight(); //初始化數(shù)據(jù) serpos = new float[2]; cicpos = new float[2]; //畫筆 paint = new Paint(); paint.setStyle(Paint.Style.STROKE); paint.setDither(true); paint.setStrokeWidth(6); paint.setAntiAlias(true); //初始化路徑 initPath(); //初始化動畫 initAnimator(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //移動畫布的遠(yuǎn)點到屏幕中心 canvas.translate(w/2,h/5); paint.setColor(Color.BLUE); //這是截取方法返回的路徑 Path dra = new Path(); //解除硬件加速,不然沒效果 dra.reset(); dra.lineTo(0,0); //設(shè)置當(dāng)前需要測量的path measure.setPath(searchPath,false); //開始截取 boolean s = measure.getSegment(measure.getLength()*value,measure.getLength(),dra,true); //繪制路徑 canvas.drawPath(dra,paint); } /** * 初始化路徑 */ public void initPath(){ paint.setColor(Color.BLUE); //搜索的圓 searchPath = new Path(); RectF rectF = new RectF(-50,-50,50,50); searchPath.addArc(rectF,45,359.9f); //輔助圓 ciclePath = new Path(); RectF rectF1 = new RectF(-100,-100,100,100); ciclePath.addArc(rectF1,45,359.9f); //測量類 measure = new PathMeasure(); measure.setPath(searchPath,false); //獲取坐標(biāo) measure.getPosTan(0,serpos,null); measure.setPath(ciclePath,false); //獲取坐標(biāo) measure.getPosTan(0,cicpos,null); //根據(jù)兩點坐標(biāo)繪制線 searchPath.lineTo(cicpos[0],cicpos[1]); } /** * 初始化動畫 */ public void initAnimator(){ ValueAnimator animator = ValueAnimator.ofFloat(0,1); animator.setDuration(2600); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { value = (float) animation.getAnimatedValue(); postInvalidate(); } }); animator.start(); } }
第一個圖大家學(xué)會了,去練習(xí)一下吧!