android 路径动画制作

 1、前言

             今天项目要用到1个类似微信发送么么哒,那种屏幕飘表情的功能,所以分析研究了1下,用到的技术应当是路径动画,不知道这样就正不正确,反正就是画1个路径线,然后对象根据这个路径去运动。所以就叫他路径动画了。

路径动画要首先要解决的问题就是怎样画这个路径?然后路径画出来后怎样取路径上的所有点的坐标值?

       这里解决这两个问题就看1个类PathMeasure 这个类接收1个path对象,然后可以根据pathMeasure.getPosTan()可以得到长度比例的坐标值。这两个问题就直接弄定了。用path画1个路径然后取点,动态移动对象,就变成了路径动画了。是否是很简单。

 

2、看效果

3、核心代码

/**
 * 撒花
 * 
 * @author yd
 *
  
 用到的知识点:
    1、android属性动画
    2、Path路径绘制
    3、贝塞尔曲线
 *
 */
public class FllowerAnimation extends View implements AnimatorUpdateListener {
 
    /**
     * 动画改变的属性值
     */
    private float phase1 = 0f;
    private float phase2 = 0f;
    private float phase3 = 0f;
 
    /**
     * 小球集合
     */
    private List<fllower> fllowers1 = new ArrayList<fllower>();
    private List<fllower> fllowers2 = new ArrayList<fllower>();
    private List<fllower> fllowers3 = new ArrayList<fllower>();
 
    /**
     * 动画播放的时间
     */
    private int time = 4000;
    /**
     * 动画间隔
     */
    private int delay = 500;
 
    /**
     * 资源ID
     */
//  private int resId = R.drawable.fllower_love;
 
    public FllowerAnimation(Context context) {
        super(context);
        init(context);
//      this.resId = resId;
    }
 
    @SuppressWarnings(deprecation)
    private void init(Context context) {
        WindowManager wm = (WindowManager) context
                .getSystemService(Context.WINDOW_SERVICE);
        width = wm.getDefaultDisplay().getWidth();
        height = (int) (wm.getDefaultDisplay().getHeight() * 3 / 2f);
 
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(2);
        mPaint.setColor(Color.BLUE);
        mPaint.setStyle(Style.STROKE);
 
        pathMeasure = new PathMeasure();
 
        builderFollower(fllowerCount, fllowers1);
        builderFollower(fllowerCount , fllowers2);
        builderFollower(fllowerCount , fllowers3);
 
    }
 
    /**
     * 宽度
     */
    private int width = 0;
    /**
     * 高度
     */
    private int height = 0;
 
    /**
     * 曲线高度个数分割
     */
    private int quadCount = 10;
    /**
     * 曲度
     */
    private float intensity = 0.2f;
 
    /**
     * 第一批个数
     */
    private int fllowerCount = 4;
 
    /**
     * 创建花
     */
    private void builderFollower(int count, List<fllower> fllowers) {
 
        int max = (int) (width * 3 / 4f);
        int min = (int) (width / 4f);
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            int s = random.nextInt(max) % (max - min + 1) + min;
            Path path = new Path();
            CPoint CPoint = new CPoint(s, 0);
            List<cpoint> points = builderPath(CPoint);
            drawFllowerPath(path, points);
            Fllower fllower = new Fllower();
            fllower.setPath(path);
            fllowers.add(fllower);
        }
 
    }
 
    /**
     * 画曲线
     * @param path
     * @param points
     */
    private void drawFllowerPath(Path path, List<cpoint> points) {
        if (points.size() > 1) {
            for (int j = 0; j < points.size(); j++) {
 
                CPoint point = points.get(j);
 
                if (j == 0) {
                    CPoint next = points.get(j + 1);
                    point.dx = ((next.x - point.x) * intensity);
                    point.dy = ((next.y - point.y) * intensity);
                } else if (j == points.size() - 1) {
                    CPoint prev = points.get(j - 1);
                    point.dx = ((point.x - prev.x) * intensity);
                    point.dy = ((point.y - prev.y) * intensity);
                } else {
                    CPoint next = points.get(j + 1);
                    CPoint prev = points.get(j - 1);
                    point.dx = ((next.x - prev.x) * intensity);
                    point.dy = ((next.y - prev.y) * intensity);
                }
 
                // create the cubic-spline path
                if (j == 0) {
                    path.moveTo(point.x, point.y);
                } else {
                    CPoint prev = points.get(j - 1);
                    path.cubicTo(prev.x + prev.dx, (prev.y + prev.dy),
                            point.x - point.dx, (point.y - point.dy),
                            point.x, point.y);
                }
            }
        }
    }
 
    /**
     * 曲线摇摆的幅度
     */
    private int range = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 70, getResources().getDisplayMetrics());
 
    /**
     * 画路径
     * 
     * @param point
     * @return
     */
    private List<cpoint> builderPath(CPoint point) {
        List<cpoint> points = new ArrayList<cpoint>();
        Random random = new Random();
        for (int i = 0; i < quadCount; i++) {
            if (i == 0) {
                points.add(point);
            } else {
                CPoint tmp = new CPoint(0, 0);
                if (random.nextInt(100) % 2 == 0) {
                    tmp.x = point.x + random.nextInt(range);
                } else {
                    tmp.x = point.x - random.nextInt(range);
                }
                tmp.y = (int) (height / (float) quadCount * i);
                points.add(tmp);
            }
        }
        return points;
    }
 
    /**
     * 画笔
     */
    private Paint mPaint;
 
    /**
     * 测量路径的坐标位置
     */
    private PathMeasure pathMeasure = null;
 
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
 
        drawFllower(canvas, fllowers1);
        drawFllower(canvas, fllowers2);
        drawFllower(canvas, fllowers3);
 
    }
 
    /**
     * 高度往上偏移量,把开始点移出屏幕顶部
     */
    private float dy = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,40, getResources().getDisplayMetrics());
     
    /**
     * 
     * @param canvas
     * @param fllowers
     */
    private void drawFllower(Canvas canvas, List<fllower> fllowers) {
        for (Fllower fllower : fllowers) {
            float[] pos = new float[2];
            canvas.drawPath(fllower.getPath(),mPaint);
            pathMeasure.setPath(fllower.getPath(), false);
            pathMeasure.getPosTan(height * fllower.getValue(), pos, null);
            canvas.drawCircle(pos[0], pos[1], 10, mPaint);
//          Bitmap bitmap = BitmapFactory.decodeResource(getResources(), resId);
//          canvas.drawBitmap(bitmap, pos[0], pos[1] - dy, null);
//          bitmap.recycle();
        }
    }
 
    public void startAnimation() {
        ObjectAnimator mAnimator1 = ObjectAnimator.ofFloat(this, phase1, 0f,
                1f);
        mAnimator1.setDuration(time);
        mAnimator1.addUpdateListener(this);
        mAnimator1.start();
        mAnimator1.setInterpolator(new AccelerateInterpolator(1f));
 
        ObjectAnimator mAnimator2 = ObjectAnimator.ofFloat(this, phase2, 0f,
                1f);
        mAnimator2.setDuration(time);
        mAnimator2.addUpdateListener(this);
        mAnimator2.start();
        mAnimator2.setInterpolator(new AccelerateInterpolator(1f));
        mAnimator2.setStartDelay(delay);
 
        ObjectAnimator mAnimator3 = ObjectAnimator.ofFloat(this, phase3, 0f,
                1f);
        mAnimator3.setDuration(time);
        mAnimator3.addUpdateListener(this);
        mAnimator3.start();
        mAnimator3.setInterpolator(new AccelerateInterpolator(1f));
        mAnimator3.setStartDelay(delay * 2);
    }
 
    /**
     * 跟新小球的位置
     * 
     * @param value
     * @param fllowers
     */
    private void updateValue(float value, List<fllower> fllowers) {
        for (Fllower fllower : fllowers) {
            fllower.setValue(value);
        }
    }
 
    /**
     * 动画改变回调
     */
    @Override
    public void onAnimationUpdate(ValueAnimator arg0) {
 
        updateValue(getPhase1(), fllowers1);
        updateValue(getPhase2(), fllowers2);
        updateValue(getPhase3(), fllowers3);
        Log.i(tag, getPhase1() + );
        invalidate();
    }
 
    public float getPhase1() {
        return phase1;
    }
 
    public void setPhase1(float phase1) {
        this.phase1 = phase1;
    }
 
    public float getPhase2() {
        return phase2;
    }
 
    public void setPhase2(float phase2) {
        this.phase2 = phase2;
    }
 
    public float getPhase3() {
        return phase3;
    }
 
    public void setPhase3(float phase3) {
        this.phase3 = phase3;
    }
 
    private String tag = this.getClass().getSimpleName();
 
    private class CPoint {
 
        public float x = 0f;
        public float y = 0f;
 
        /** x-axis distance */
        public float dx = 0f;
 
        /** y-axis distance */
        public float dy = 0f;
 
        public CPoint(float x, float y) {
            this.x = x;
            this.y = y;
        }
    }
 
}

下载地址: http://download.csdn.net/detail/hxc2008q/8473053

 

猜你喜欢

转载自lishuaishuai.iteye.com/blog/2295309
今日推荐