天天看點

直播系統源碼開發,如何實作點贊動畫效果?

在直播系統源碼開發中,可以通過點選螢幕點贊按鈕,會有不同顔色的心型從底部冒出,并按照不規則的路線運動,在運動過程中,伴随着各種動畫效果,這也是我們經常會見到的點贊特效,今天就來看一看是如何實作的吧。

好了,話不多說,直接上代碼:

/**
 * Created by DELL on 2017/9/16.
 * Description : 花束點贊效果
 */

public class PraiseView extends RelativeLayout {

    private int[] drawables;
    private Context mContext;
    //圖檔的寬高
    private int mDrawableHeight;
    private int mDrawableWidth;

    //随機數
    private Random mRandom;

    public PraiseView(Context context) {
        this(context,null);
    }

    public PraiseView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public PraiseView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        this.mContext = context;
        //建立随機數 在後面的貝塞爾取點鐘會用到
        mRandom = new Random();
        //初始化心形圖檔
        drawables = new int[]{R.drawable.pl_blue,R.drawable.pl_red,R.drawable.pl_yellow};

        //擷取心形圖檔的寬高
        Drawable drawable = ContextCompat.getDrawable(context,drawables[0]);
        mDrawableHeight = drawable.getIntrinsicHeight();
        mDrawableWidth = drawable.getIntrinsicWidth();
    }

    //在螢幕底部添加心形圖檔
    public void addDrawables(){
        final ImageView imageView = new ImageView(mContext);
        imageView.setImageResource(drawables[mRandom.nextInt(drawables.length-1)]);
        RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
        params.addRule(ALIGN_PARENT_BOTTOM);
        params.addRule(CENTER_HORIZONTAL);
        imageView.setLayoutParams(params);
        addView(imageView);

        //建立并開啟動畫效果
        AnimatorSet animatorSet = getAnimator(imageView);
        animatorSet.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                super.onAnimationEnd(animation);
                //在動畫執行結束之後,移除該view
                removeView(imageView);
            }
        });
        animatorSet.start();
    }

    //建立動畫

    /**
     * 剛開始做縮放和漸變動畫  結束後開始做移動動畫
     * @param imageView
     * @return
     */
    private AnimatorSet getAnimator(ImageView imageView){
        //縮放動畫
        ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(imageView,"scaleX",0.3f,1f);
        ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(imageView,"scaleY",0.3f,1f);
        //漸變動畫
        ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(imageView,"alpha",0.3f,1f);

        AnimatorSet set = new AnimatorSet();
        set.playTogether(scaleXAnimator,scaleYAnimator,alphaAnimator);
        set.setDuration(300);

        //建立平移動畫并添加到set執行完成之後執行
        AnimatorSet wholeAnimator = new AnimatorSet();
        //按照順序執行
        wholeAnimator.playSequentially(set,getBeizerAnimator(imageView));
        return wholeAnimator;
    }

    private ValueAnimator getBeizerAnimator(final ImageView imageView){
        //首先先确定需要用到的四個點
        //點0是在圖檔開始的中心點
        final PointF point0 = new PointF(getWidth()/2 - mDrawableWidth/2,getHeight() - mDrawableHeight);
        //點1 點2是貝塞爾曲線的控制點  需要控制的是,點2的高度要大于點1的高度
        PointF point1 = getPoint(1);
        PointF point2 = getPoint(2);
        PointF point3 = new PointF(mRandom.nextInt(getWidth()/2) - mDrawableWidth/2,0);
        BeizerEvalator beizerEvalator = new BeizerEvalator(point1,point2);
        ValueAnimator beizerAnimator = ObjectAnimator.ofObject(beizerEvalator,point0,point3);
        beizerAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        beizerAnimator.setDuration(4000);
        beizerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //在運作過程中會調用該方法
                PointF pointF = (PointF) animation.getAnimatedValue();
                imageView.setX(pointF.x);
                imageView.setY(pointF.y);

                //設定移動過程中的漸變
                //首先擷取目前的fraction
                float fraction = animation.getAnimatedFraction();
                imageView.setAlpha(1-fraction);
            }
        });
        return beizerAnimator;
    }

    private PointF getPoint(int i){
        return new PointF(mRandom.nextInt(getWidth())- mDrawableWidth,mRandom.nextInt(getHeight()/2) + (i-1)*getHeight()/2);
    }
}
           

然後,我們需要一個估值器,來确定在某一時刻,沿着貝塞爾曲線的路徑的點(這邊,其實隻要套公式就可以了)

/**
 * Created by DELL on 2017/9/16.
 * Description : 貝塞爾運動軌迹估值器
 */

public class BeizerEvalator implements TypeEvaluator<PointF> {

    private PointF point1,point2;

    public BeizerEvalator(PointF point1,PointF point2){
        this.point1 = point1;
        this.point2 = point2;
    }

    //直接套用貝塞爾三階公式
    @Override
    public PointF evaluate(float fraction, PointF point0, PointF point3) {

        PointF pointF = new PointF();

        pointF.x = point0.x*(1-fraction)*(1-fraction)*(1-fraction)
                + 3*point1.x*fraction*(1-fraction)*(1-fraction)
                + 3*point2.x*fraction*fraction*(1-fraction)
                + point3.x*fraction*fraction*fraction;

        pointF.y = point0.y*(1-fraction)*(1-fraction)*(1-fraction)
                + 3*point1.y*fraction*(1-fraction)*(1-fraction)
                + 3*point2.y*fraction*fraction*(1-fraction)
                + point3.y*fraction*fraction*fraction;

        return pointF;
    }
}
           

相關注釋都加在代碼中了,以上就是直播系統源碼開發,如何實作點贊動畫效果的全部内容了。

繼續閱讀