Android 實現Path曲線動畫兩種方案

Path動畫是一種很是特殊的動畫,能夠理解爲動畫沿着Path路徑移動。構建Path動畫有兩種方式,第一種是基於TypeEvalutor,該類用於控制View的狀態、位置等。另外一種是經過PathMeasure,這種能夠更加直觀的定義路徑,一樣也能夠定義draw繪圖等。html

 

方案一:經過TypeEvalutor定義Path動畫android

曲線動畫很常見,但最著名的是貝塞爾曲線動畫(貝塞爾曲線的數學原理canvas

class BezierEvaluator implements TypeEvaluator<PointF>{  
  
        @Override  
        public PointF evaluate(float fraction, PointF startValue,  
                PointF endValue) {  
            final float t = fraction;  
            float oneMinusT = 1.0f - t;  
            PointF point = new PointF();  
              
            PointF point0 = (PointF)startValue;  
              
            PointF point1 = new PointF();  
            point1.set(width, 0);  
              
            PointF point2 = new PointF();  
            point2.set(0, height);  
              
            PointF point3 = (PointF)endValue;  
              
            point.x = oneMinusT * oneMinusT * oneMinusT * (point0.x)   
                    + 3 * oneMinusT * oneMinusT * t * (point1.x)  
                    + 3 * oneMinusT * t * t * (point2.x)  
                    + t * t * t * (point3.x);  
              
            point.y = oneMinusT * oneMinusT * oneMinusT * (point0.y)   
                    + 3 * oneMinusT * oneMinusT * t * (point1.y)  
                    + 3 * oneMinusT * t * t * (point2.y)  
                    + t * t * t * (point3.y);             
            return point;  
        }     
    }
valueAnimator.addUpdateListener(new AnimatorUpdateListener() {            
            @Override  
            public void onAnimationUpdate(ValueAnimator animation) {  
                PointF pointF = (PointF)animation.getAnimatedValue();  
                button.setX(pointF.x);  
                button.setY(pointF.y);  
            }  
        });

 

方案二:PathMeasure動畫ide

可是還有一類動畫就是Path動畫,經過PathMeasure實現Object在Path路徑上動畫post

public class DynamicHeartView extends View {  
  
    private static final String TAG = "DynamicHeartView";  
    private static final int PATH_WIDTH = 2;  
    // 起始點  
    private static final int[] START_POINT = new int[] {  
            300, 270  
    };  
    // 愛心下端點  
    private static final int[] BOTTOM_POINT = new int[] {  
            300, 400  
    };  
    // 左側控制點  
    private static final int[] LEFT_CONTROL_POINT = new int[] {  
            450, 200  
    };  
    // 右側控制點  
    private static final int[] RIGHT_CONTROL_POINT = new int[] {  
            150, 200  
    };  
  
    private PathMeasure mPathMeasure;  
    private Paint mPaint;  
    private Path mPath;  
    private float[] mCurrentPosition = new float[2];  
  
    public DynamicHeartView(Context context) {  
        super(context);  
        init();  
    }  
  
    private void init() {  
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);  
        mPaint.setStyle(Style.STROKE);  
        mPaint.setStrokeWidth(PATH_WIDTH);  
        mPaint.setColor(Color.RED);  
  
        mPath = new Path();  
        mPath.moveTo(START_POINT[0], START_POINT[1]);  
        mPath.quadTo(RIGHT_CONTROL_POINT[0], RIGHT_CONTROL_POINT[1], BOTTOM_POINT[0],  
                BOTTOM_POINT[1]);  
        mPath.quadTo(LEFT_CONTROL_POINT[0], LEFT_CONTROL_POINT[1], START_POINT[0], START_POINT[1]);  
  
        mPathMeasure = new PathMeasure(mPath, true);  
        mCurrentPosition = new float[2];  
    }  
  
    @Override  
    protected void onDraw(Canvas canvas) {  
        super.onDraw(canvas);  
        canvas.drawColor(Color.WHITE);  
        canvas.drawPath(mPath, mPaint);  
  
        canvas.drawCircle(RIGHT_CONTROL_POINT[0], RIGHT_CONTROL_POINT[1], 5, mPaint);  
        canvas.drawCircle(LEFT_CONTROL_POINT[0], LEFT_CONTROL_POINT[1], 5, mPaint);  
  
        // 繪製對應目標  
        canvas.drawCircle(mCurrentPosition[0], mCurrentPosition[1], 10, mPaint);  
    }  
  
    // 開啓路徑動畫  
    public void startPathAnim(long duration) {  
        // 0 - getLength()  
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, mPathMeasure.getLength());  
        Log.i(TAG, "measure length = " + mPathMeasure.getLength());  
        valueAnimator.setDuration(duration);  
        // 減速插值器  
        valueAnimator.setInterpolator(new DecelerateInterpolator());  
        valueAnimator.addUpdateListener(new AnimatorUpdateListener() {  
  
            @Override  
            public void onAnimationUpdate(ValueAnimator animation) {  
                float value = (Float) animation.getAnimatedValue();  
                // 獲取當前點座標封裝到mCurrentPosition  
                mPathMeasure.getPosTan(value, mCurrentPosition, null);  
                postInvalidate();  
            }  
        });  
        valueAnimator.start();  
  
    }  
}

http://blog.csdn.net/vrix/article/details/39206975動畫

http://blog.csdn.net/tianjian4592/article/details/47067161lua

http://www.2cto.com/kf/201503/380377.html.net

http://blog.csdn.net/androidzhaoxiaogang/article/details/8680330code

http://blog.csdn.net/linmiansheng/article/details/18763987htm

相關文章
相關標籤/搜索