撸一个直播点赞动画

作者: 尹star | 来源:发表于2016-07-10 21:04 被阅读4593次

    最近在做直播相关的东西,这个动画是IOS先撸出来的,后来android这边要模仿,大部分直播应用都有很炫酷的点赞动画,所以也没什么好稀奇的。如果有现成的轮子了,就没必要自己再造了,后来参照了程序亦非猿的实现,做了些修改,最终效果还不错。

    live.gif

    刚开始自己造轮子的时候也走了些弯路,最初是给这些图标一些随机的初始速度和偏移量然后慢慢上升,效果总是不大好,差了点意思。后来仔细研究发现这些图标上升的路线并不是直线,而是一个三阶贝塞尔曲线。

      一阶贝塞尔曲线,实际上就是一条连接两点的直线段。
      二阶贝塞尔曲线,就是两点间的一条抛物线,利用一个控制点来控制抛物线的形状。
      三阶贝塞尔曲线,则需要一个起点,一个终点,两个控制点来控制曲线的形状。
    

    三节贝塞尔曲线的公式


    公式.png

    公式中:P0,是我们的起点,P3是终点,P1,P2是途径的两个点,而t则是一个因子,取值范围是0-1。
    整个曲线的生成过程


    过程.gif

    实现代码如下,调用的时候只需要在构造方法中传入两个随机点即可。

        public class BesselEvaluator implements TypeEvaluator<float[]> {
            private float point1[] = new float[2], point2[] = new float[2];
    
            public BesselEvaluator(float[] point1, float[] point2) {
                this.point1 = point1;
                this.point2 = point2;
            }
    
            @Override
            public float[] evaluate(float fraction, float[] point0, float[] point3) {
                float[] currentPosition = new float[2];
                currentPosition[0] = point0[0] * (1 - fraction) * (1 - fraction) * (1 - fraction)
                        + point1[0] * 3 * fraction * (1 - fraction) * (1 - fraction)
                        + point2[0] * 3 * (1 - fraction) * fraction * fraction
                        + point3[0] * fraction * fraction * fraction;
                currentPosition[1] = point0[1] * (1 - fraction) * (1 - fraction) * (1 - fraction)
                        + point1[1] * 3 * fraction * (1 - fraction) * (1 - fraction)
                        + point2[1] * 3 * (1 - fraction) * fraction * fraction
                        + point3[1] * fraction * fraction * fraction;
                return currentPosition;
            }
        }
    

    详细的动画实现可以参考一步一步教你实现Periscope点赞效果,但很显然我这里完成点赞动画,任务还没有完成。有几个问题需要解决:允许连续点赞,而且是计数的,什么时候把点赞的数量抛给服务器;我怎么看到其他用户点赞,或者其他用户怎么看的到我点赞。

    先看第一个问题吧,什么时候把点赞数量抛给服务器?由于产品经理带着小姨子跑路了,Ios和android两个端的策略还不太一样,但我们达成的基本共识就是:不能点一次抛一次,抛的次数越少越好。Ios是本地维护一个count,没隔一段时间检测count有增加,就抛一次。android这里是连续点击的时间间隔大于一个约定值,就认为本轮点赞结束,然后抛一次。以前有研究过单击双击,这次连续点击也来了,该来的总要来的。

    public class MainActivity extends AppCompatActivity {
    
        long mLastTime = 0;
        long mCurTime = 0;
        private final int DELAY = 500;//连续点击的临界点
        BubbleView bubbleView;
        private int mClickCount = 0;
        private int currLikeCount;
        private TextView likeCount;
        private Timer delayTimer;
        private TimerTask timeTask;
    
        private Handler mHandler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                praiseRequest(mClickCount);
                delayTimer.cancel();
                super.handleMessage(msg);
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
            setSupportActionBar(toolbar);
            bubbleView=(BubbleView)findViewById(R.id.praise_anim);
            bubbleView.setDefaultDrawableList();
            likeCount = (TextView) findViewById(R.id.like_count);
            FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
            fab.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
    
                    mCurTime = System.currentTimeMillis();
                    if (mCurTime - mLastTime < DELAY) {
                        mClickCount++;
                    } else {
                        mClickCount = 1;
                    }
                    currLikeCount++;
                    likeCount.setText(String.valueOf(currLikeCount));
                    delay();
                    mLastTime = mCurTime;
                    bubbleView.startAnimation(bubbleView.getWidth(), bubbleView.getHeight());
                }
            });
        }
    
        private void delay() {
            if (timeTask != null)
                timeTask.cancel();
    
            timeTask = new TimerTask() {
                @Override
                public void run() {
                    Message message = new Message();
                    mHandler.sendMessage(message);
                }
            };
            delayTimer = new Timer();
            delayTimer.schedule(timeTask, DELAY);
        }
    
        /**
         * 点赞请求网络
         */
        private void praiseRequest(int count) {
    
        }
    }
    

    第二个问题由于暂时没条件做推送,所以只能客户端每隔一段时间轮一次接口了,如果相比较上次数量有增加,动画上就弹出相应数量的爱心数,这里就需要给屏幕上允许出现的爱心数量设置一个最大值,要不然一瞬间弹出几百个甚至上千个肯定要悲剧了。


    576DB36E-F179-47A0-A216-8C05381BCC94-1540-0000D86DB0CDA3D2.gif test.gif

    最后还是贴上代码,需要的自取:GitHub

    相关文章

      网友评论

      • Alee_:正好项目有这个需求,我也来撸一把

      本文标题:撸一个直播点赞动画

      本文链接:https://www.haomeiwen.com/subject/dwtgdttx.html