最近在做直播相关的东西,这个动画是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
后期将做进一步的拓展,实现详情效果


放yy直播点赞动画的更多相关文章

  1. iOS直播点赞动画,iOS直播心型点赞动画

    https://github.com/songxing10000/LikeAnimation-PraiseAnimation

  2. 巧用 transition 实现短视频 APP 点赞动画

    在各种短视频界面上,我们经常会看到类似这样的点赞动画: 非常的有意思,有意思的交互会让用户更愿意进行互动. 那么,这么有趣的点赞动画,有没有可能使用纯 CSS 实现呢?那当然是必须的,本文,就将巧妙的 ...

  3. twitter点赞动画详解

    今天在微博上看到@过气网红一丝 的一篇微博,codepen上贴出了twitter点赞那个动画效果的源码,地址 http://codepen.io/yisi/pen/LpXVJb .我看了下效果很好看, ...

  4. uniapp - 点赞动画插件

    更新时间: 2019/8/31 - 点击下载demo 点赞动画插件配合animate.css更好用! 该组件参考于:https://github.com/OYsun/VueStar/tree/mast ...

  5. Vue 左右翻页,点赞动画

    因做小活动比较多,使用了一些动画,做些笔记,供大家参考 翻页动画 router -> index.js import Vue from 'vue'; import Router from 'vu ...

  6. [deviceone开发]-直播APP心形点赞动画示例

    一.简介 这个示例展示do_Animator组件的简单使用,通过点击"点赞"按钮,不断弹出心形图片,向上动画漂移到顶部消失.间隔时间和上下左右移动的步长都是一定范围的随机值. 二. ...

  7. 直播点赞,上升的动画-- CAKeyFrameAnimation

    // //  ViewController.m //  DMHeartFlyAnimation // //  Created by Rick on 16/3/9. //  Copyright © 20 ...

  8. [deviceone开发]-心形点赞动画示例

    一.简介 这个示例展示do_Animator组件的简单使用,通过点击"点赞"按钮,不断弹出心形图片,向上动画漂移到顶部消失.间隔时间和上下左右移动的步长都是一定范围的随机值.二.效 ...

  9. CSS3点赞动画特效源码下载

    体验效果:http://hovertree.com/texiao/jquery/62/ 效果图: 下载:http://hovertree.com/h/bjaf/1dvh9ym6.htm 特效库:htt ...

随机推荐

  1. 深入Java虚拟机(1)——Java体系结构

    Java体系结构 Java体系结构包括四个独立但相关的技术: 1.Java程序设计语言 2.Java class文件格式 3.Java应用编程接口(API) 4.Java虚拟机 当编写并运行一个Jav ...

  2. OSTC 2015

    上周六去北京参加了OSTC 2015开源技术大会,并分享了<Spark技术内幕>,主要涵盖了Spark Core的核心实现.我主要以WordCount为例,讲解了任务调度的具体实现,资源分 ...

  3. iOS 中隐藏UITableView最后一条分隔线

    如何优雅的隐藏UITableView中最后一条分割线? 这个问题是很常见,却又不太容易解决的. 可能通常的做法都是隐藏UITableView的分割线,自定义一条. 最近在使用弹出菜单的时候,同样遇到了 ...

  4. 剑指Offer——网易笔试题+知识点总结

    剑指Offer--网易笔试题+知识点总结 Fibonacci package cn.edu.ujn.nk; import java.util.ArrayList; import java.util.S ...

  5. Mybatis源码学习之TypeHandler

    ORM框架最重要功能是将面向对象方法中的对象和关系型数据库中的表关联了起来,在关联过程中就必然涉及到对象中的数据类型和数据库中的表字段类型的转换,Mybatis中的org.apache.ibatis. ...

  6. NSDictionary writeToFile:atomically: 时失败

    一.现象:如下图,当NSDictionary调用 writeToFile:atomically: 时,如果容器里面包含的对象(即通过 objectForKey: 拿到的对象),为非property l ...

  7. OpenCV+OpenGL 双目立体视觉三维重建

    0.绪论 这篇文章主要为了研究双目立体视觉的最终目标--三维重建,系统的介绍了三维重建的整体步骤.双目立体视觉的整体流程包括:图像获取,摄像机标定,特征提取(稠密匹配中这一步可以省略),立体匹配,三维 ...

  8. Java进阶(四十七)Socket通信

    Java进阶(四十七)Socket通信   今天讲解一个 Hello Word 级别的 Java Socket 通信的例子.具体通讯过程如下: 先启动Server端,进入一个死循环以便一直监听某端口是 ...

  9. JAVA面向对象-----值交换(基本数据类型 数组类型 对象的值 字符串的)

    JAVA面向对象-–值交换 基本数据类型交换 数组类型交换 对象的值交换 字符串的值交换 恩,没错,又是贴图,请大家见谅,我也是为了多写几个文章,请大家谅解. 字符串的值交换: 交换值失败. 这个文章 ...

  10. char能表示(-128~127)

    char 的取值范围是 -128 ~127 注:数0的补码表示是唯一的: +0的补码=+0的反码=+0的原码=00000000 -0的补码=11111111+1=00000000(mod 2的8次方) ...