android 路径动画制作

1、前言

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

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

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

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 pathif (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;@Overrideprotected 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);}}/** * 动画改变回调 */@Overridepublic 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;}}}4、项目地址

让我们从自身的禁锢中放心地飞出去,重新审视自己,

android 路径动画制作

相关文章:

你感兴趣的文章:

标签云: