視頻直播中的心形漂浮效果

實現效果:

這裏寫圖片描述

思路:

1.首先要給心形圖片創建一個平滑的懸浮路徑,那就要用到貝塞爾曲線,這裏採用自定義TypeEvaluator實現。
2.路徑有了,就要考慮實現動畫的兩個步驟
a.縮放,伴隨透明度變化
b.底部懸浮到頂部
這裏是用的是Matrix
3.自定義View,然後繪製心形圖片。
詳細步驟,看源碼

代碼:

1.自定義BezierEvaluator

package com.test.paintdemo.loveflyover;

import android.animation.TypeEvaluator;
import android.graphics.PointF;

/**
 * Created by ygdx_lk on 17/6/26.
 */

public class BezierEvaluator implements TypeEvaluator<PointF> {
    private final  PointF p0, p3;
    public BezierEvaluator(PointF point0, PointF point3){
        this.p0 = point0;
        this.p3 = point3;
    }

    @Override
    public PointF evaluate(float t, PointF p1, PointF p2) {
        //貝塞爾曲線的三次方公式
        PointF pointF = new PointF();
        pointF.x = (float) (p0.x * Math.pow((1 - t), 3) + 3 * p1.x * t * Math.pow((1 - t), 2) + 3 * p2.x * Math.pow(t, 2) * (1 - t) + p3.x * Math.pow(t, 3));
        pointF.y = (float) (p0.y * Math.pow((1 - t), 3) + 3 * p1.y * t * Math.pow((1 - t), 2) + 3 * p2.y * Math.pow(t, 2) * (1 - t) + p3.y * Math.pow(t, 3));
        return pointF;
    }
}

2.創建FlyOverModel

package com.test.paintdemo.loveflyover;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PointF;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.AnticipateInterpolator;
import android.view.animation.AnticipateOvershootInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import android.view.animation.OvershootInterpolator;

import com.test.paintdemo.R;

import java.util.Random;

/**
 * Created by ygdx_lk on 17/6/26.
 */

public class FlyOverModel {
    private static final String TAG = "FlyOverModel";
    private Paint mPaint;
    private PointF p0, p1, p2, p3;//p0起點,p1、p2拐點,p3終點
    private float love_w, love_h;//愛心的寬高
    private Bitmap mBitMap;//圖片
    private Matrix matrix;
    //圖片
    private int[] resources = {R.drawable.red, R.drawable.blue, R.drawable.yellow};
    //差值器
    private Interpolator[] interpolator = {new AccelerateDecelerateInterpolator(),
            new AnticipateInterpolator(),
            new OvershootInterpolator(),
            new AnticipateOvershootInterpolator(),
            new LinearInterpolator(),
            new AccelerateInterpolator(),
            new DecelerateInterpolator()
    };

    public FlyOverModel(final Context context, final int width, final int height, final Invalidate invalidate){
        //初始化畫筆
        mPaint = new Paint();
        mPaint.setAntiAlias(true);

        //矩陣變換,用來控制圖片的縮放位移
        matrix = new Matrix();

        //三次方貝塞爾曲線:初始化四個點,p0起點,p1、p2拐點,p3終點
        p0 = new PointF();
        p1 = new PointF();
        p2 = new PointF();
        p3 = new PointF();


        //初始化bitmap
        mBitMap = BitmapFactory.decodeResource(context.getResources(), resources[new Random().nextInt(resources.length)]);
        //獲取bitmap的寬高
        love_w = mBitMap.getWidth();
        love_h = mBitMap.getHeight();


        //p0正好將圖片貼底居中顯示
        p0.x = (width - love_w) / 2;
        p0.y = height - love_h;

        p2.x = (float) (Math.random() * width);
        p2.y = (float) (Math.random() * height / 2);

        p1.x = (float) (Math.random() * width);
        p1.y = (float) ((1 + Math.random()) * height / 2);

        //p3正好圖片移出屏幕
        p3.x = (float) (Math.random() * width);
        p3.y = -love_h;


        //縮放動畫
        ValueAnimator scaleAnimator = ValueAnimator.ofFloat(0, 1);
        scaleAnimator.setDuration(1000);
        scaleAnimator.setInterpolator(new LinearInterpolator());
        scaleAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //平移到底部
                matrix.setTranslate(p0.x, p0.y);
                //以圖片中心底部爲軸,進行縮放
                matrix.preScale(animation.getAnimatedFraction(), animation.getAnimatedFraction(), love_w / 2, love_h);
                //設置畫筆透明度
                mPaint.setAlpha((int) (255 * animation.getAnimatedFraction()));
                invalidate.invalidate();
            }
        });

        //位移動畫
        BezierEvaluator bezierEvaluator = new BezierEvaluator(p0, p3);
        ValueAnimator valueAnimator = ValueAnimator.ofObject(bezierEvaluator, p1, p2);
        valueAnimator.setInterpolator(interpolator[new Random().nextInt(interpolator.length)]);
        valueAnimator.setDuration(3000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                PointF pointF = (PointF) animation.getAnimatedValue();
                matrix.reset();
                matrix.setTranslate(pointF.x, pointF.y);
                invalidate.invalidate();
            }
        });
        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.play(valueAnimator).after(scaleAnimator);
        animatorSet.start();
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                //如果動畫結束了,重新開始動畫
                animation.start();
                super.onAnimationEnd(animation);
            }
        });
    }

    interface Invalidate{
        void invalidate();
    }

    /**
     * 繪製bitmap
     * @param canvas
     */
    public void drawBitmap(Canvas canvas){
        canvas.drawBitmap(mBitMap, matrix, mPaint);
    }
}

3.創建自定義View:LoveFlyOver

package com.test.paintdemo.loveflyover;

import android.content.Context;
import android.graphics.Canvas;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by ygdx_lk on 17/6/26.
 */

public class LoveFlyOver extends View {
    private int width;//控件寬
    private int height;//控件高
    private static final String TAG = "loveFlyOver";
    private List<FlyOverModel> list;
    public LoveFlyOver(Context context) {
        this(context, null);
    }

    public LoveFlyOver(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        list = new ArrayList<>();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        //控件寬高
        width = w;
        height = h;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                //點擊後添加圖片
                addLove();
                break;
        }
        return super.onTouchEvent(event);
    }

    private void addLove(int count){
        for (int i = 0; i < count; i++) {
            addLove();
        }
    }

    //添加心形圖片
    private void addLove(){
        FlyOverModel flyOverModel = new FlyOverModel(getContext(), width, height, new FlyOverModel.Invalidate() {
            @Override
            public void invalidate() {
                postInvalidate();
            }
        });
        list.add(flyOverModel);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //繪製
        for (FlyOverModel item : list) {
            item.drawBitmap(canvas);
        }
    }
}
發佈了101 篇原創文章 · 獲贊 29 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章