欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

视频直播中的心形漂浮效果

程序员文章站 2022-07-12 22:59:37
...

实现效果:

视频直播中的心形漂浮效果

思路:

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);
        }
    }
}
相关标签: matrix 动画