视频直播中的心形漂浮效果
程序员文章站
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);
}
}
}