Android動(dòng)畫(huà)進(jìn)階PathMeasure

PathMeasure

作用:測(cè)量并獲取Path的信息,用于繪制Path路徑實(shí)現(xiàn)動(dòng)畫(huà)效果

ValueAnimator在這里不會(huì)講解,不過(guò)至關(guān)重要,是動(dòng)畫(huà)的發(fā)動(dòng)機(jī)!

基本路徑繪制

預(yù)覽:

普通路徑繪制.mp4_1491231595.gif
  1. 生成完整的目標(biāo)路徑
  2. 初始化PathMeasure對(duì)象
  3. PathMeasure.setPath(targetPath,true) 測(cè)量路徑
  4. mPathMeasure.getLength(); 獲取路徑的總長(zhǎng)度
  5. 初始化動(dòng)態(tài)的路徑 mDstPath
  6. mPathMeasure.getSegment(startD, stopD, mDstPath, true); : 根據(jù)傳入的起始值終止值(相當(dāng)于要截取路徑的部分),將路徑賦值給mDstPath
  7. 使用ValueAnimator產(chǎn)生一個(gè)增長(zhǎng)值來(lái)控制 終止值 如:float stopD = mAnimatedValue * mLength;
  8. 最后將 mDstPath 繪制出來(lái),就可以實(shí)現(xiàn)路徑的逐步繪制效果了
//完整的圓的路徑
        mCirclePath = new Path();
        //路徑繪制每段截取出來(lái)的路徑
        mDstPath = new Path();

        mCirclePath.addCircle(0, 0, 200, Path.Direction.CW);

        //路徑測(cè)量類(lèi)
        mPathMeasure = new PathMeasure();
        //測(cè)量路徑
        mPathMeasure.setPath(mCirclePath, true);

        //獲取被測(cè)量路徑的總長(zhǎng)度
        mLength = mPathMeasure.getLength();

        mValueAnimator = ValueAnimator.ofFloat(0, 1);
        mValueAnimator.setDuration(2000);
        mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
        mValueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //獲取從0-1的變化值
                mAnimatedValue = (float) animation.getAnimatedValue();
                //不斷刷新繪圖,實(shí)現(xiàn)路徑繪制
                invalidate();
            }
        });


@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //必須要有l(wèi)ineTo(0,0)才可以實(shí)現(xiàn)路徑的完整繪制
        mDstPath.reset();
        mDstPath.lineTo(0, 0);
        float stopD = mAnimatedValue * mLength;
        float startD = 0;

        //獲取當(dāng)前進(jìn)度的路徑,同時(shí)賦值給傳入的mDstPath
        mPathMeasure.getSegment(startD, stopD, mDstPath, true);

        canvas.save();
        canvas.translate(300, 300);
        canvas.drawPath(mDstPath, mPaint);
        canvas.restore();
    }


Windows風(fēng)格加載動(dòng)畫(huà)繪制

預(yù)覽:

windows路徑繪制.mp4_1491231732.gif
  • 實(shí)現(xiàn)這種效果只要在上面的基礎(chǔ)上動(dòng)態(tài)改變我們所截取的startD就可以了
    只要加上這一句代碼
 //通過(guò)設(shè)置其實(shí)位置的變化來(lái)實(shí)現(xiàn)Window加載風(fēng)格
            startD = (float) (stopD - ((0.5 - Math.abs(mAnimatedValue - 0.5)) * mLength));

獲取路徑點(diǎn)的坐標(biāo)和角度

預(yù)覽:

箭頭路徑繪制.mp4_1491231817.gif

主要涉及mPathMeasure.getPosTan(float distance, float pos[], float tan[]) 這個(gè)API

  • distance : 這個(gè)參數(shù)就是確定要獲取路徑上那個(gè)位置的點(diǎn)
  • pos[] : 根據(jù)distance返回 點(diǎn)的坐標(biāo)信息并保存在傳入的pos[]內(nèi), X保存在pos[0], Y則在pos[1]
  • tan[] : 根據(jù)distance返回 點(diǎn)的角度信息并保存?zhèn)魅雝an[]內(nèi) ,主要結(jié)合float degree = (float) (Math.atan2(mTan[1], mTan[0]) * 180 / Math.PI);
    這個(gè)公式 就可以求得當(dāng)前點(diǎn)的切線和X正半軸的角度

具體繪制:

  if (mIsArrow) {
            //mPos是當(dāng)前路徑點(diǎn)的坐標(biāo)
            //mTan通過(guò)下面公式可以得到當(dāng)前點(diǎn)的切線角度
            mPathMeasure.getPosTan(mAnimatedValue * mLength, mPos, mTan);
            float degree = (float) (Math.atan2(mTan[1], mTan[0]) * 180 / Math.PI);
            Log.e("lzh", "onDraw:  degree=" + degree);
            canvas.save();
            canvas.translate(300, 300);
            canvas.drawCircle(mPos[0], mPos[1], 10, mPaint);
            canvas.rotate(degree);
            //繪制切線
            canvas.drawLine(0, -200, 200, -200, mPaint);
            canvas.restore();

        }

最后:
PathMeasure大大簡(jiǎn)化了我們?nèi)?shí)現(xiàn)一個(gè)復(fù)雜路徑的成本,只需要繪制好一個(gè)Path,剩下的就都交給PathMeasure搞定!
當(dāng)然,其實(shí)動(dòng)畫(huà)本身最可貴的還是源于一個(gè)好的想法。
如果覺(jué)有有用,可以點(diǎn)贊鼓勵(lì)一下哈O(∩_∩)O~~

附上:代碼Github

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容