由于产品与运营需求需要实现形态更为丰富的动画,例如中秋节的“玉兔”彩蛋、近期的“下雪”彩蛋和后续会上线的新玩法(暂时保密)等,需要有功能更强大更全面的通用动画能力。基于此诉求,借鉴于现有的成熟动画组件的经验,构建了QQAnimationKit并在实现了一些基础的通用能力。
通过分析,希望实现QQAnimationKit第一个组件,能力包括:粒子效果、重力效果、碰撞效果、粒子路径、支持多资源类型(静态&动态)、支持交互等。
目前移动端支持粒子效果的动画组件较多,考虑到支持交互及未来可扩充更多新的资源类型等,最终决定选择CoreMotion+UIDynamic作为基础,通过扩充能力实现QQAnimationKit中功能更强大的第一个动画组件--QQGravityAnimation2D。
粒子通过继承自UIView并遵守UIDynamicItem协议实现,见QQGravity2DBody。粒子拥有与重力、碰撞、推力和交互相关的属性。粒子支持PNG、lottie动画的播放(为提高性能,此处使用rlottie,原因分析见动画预研文章),后续如有必要可扩展APNG/PAG等格式。粒子中封装了很多细节,例如可配置的逐渐消失时间、生存时间、点击跳转url等,这些能力可根据需要进行扩展。
重力的计算是UIGravityBehavior提供的。重力方向通过监听加速度计CMMotionManager的变化,间隔一定时间读取设备当前的信息并设置为UIGravityBehavior的gravityDirection。将UIGravityBehavior添加到UIDynamicAnimator,以此实现重力效果。至此,重力粒子动画组件完成。
碰撞的计算是UICollisionBehavior提供的,与重力较为类似。不同的是,由于碰撞需要轮廓信息,默认的碰撞轮廓是外接矩形或内接圆,实际体验较差,不够真实。此处借助于重写QQGravity2DBody中- (UIDynamicItemCollisionBoundsType)collisionBoundsType和- (UIBezierPath *)collisionBoundingPath来实现贝塞尔曲线的自定义轮廓计算。这里遇到一个问题,如何简单表示粒子的轮廓,思考后提出一种较为简单的思路,通过宽、高和圆角来实现矩形、圆角矩形、圆和椭圆等轮廓。经过多次使用发现,这种简单的思路作用很大!很好的使用于基于此动画的已上线需求中。这种较为精确的轮廓计算效果表现为单层的平铺效果,为模拟真实,可将碰撞轮廓设置与真实轮廓不一致,构造一种多层的效果。这是一种较为巧妙的实现方式。至此,带碰撞的重力粒子动画组件完成。
为了使粒子路径由2个因素决定:外力(含重力、碰撞与推力)与速度,包括大小和方向。为了更好适应多变的业务诉求,每个粒子都提供了一个脉冲型的推力作用,作为粒子运动的初始状态。由于推力和重力、碰撞一样,
是一个“作用场”,若所有粒子都存在于一个推力场中,那么对一个的初始推力同时也会影响到其他粒子,这是我们不希望看到的。因此,为每个粒子提供一个推力场是一个比较好的解决方案。至此,带初始状态和碰撞的重力粒子动画组件完成。
某天忽然想到一个问题,既然上述重力粒子动画组件是以真实的重力矢量来作用的,那我是否可以将其泛化,以实现一个更为强大的可配置外力作用的粒子动画组件呢?答案是肯定的。于是,通过一个可配置的重力系数,与真实的重力相乘,将重力粒子动画组件带到了新的高度--外力粒子动画组件。可模拟浮力实现气球和孔明灯、可模拟流星滑落和下雨下雪...功能得到进一步增强。同时,由于多粒子的存在和粒子对lottie等资源的支持,转变对粒子的理解和思维,将其理解为某个“动画粒子”,扩展粒子本身的形态,不再局限于粒子就是单个粒子对象。以此思维可实现更丰富的动画,期待iOS QQ后续动画陆续和大家见面~
目前iOS QQ 聊天彩蛋已全面接入QQAnimationKit并实现了一套层次清晰、功能强大、极其适合运营的聊天彩蛋模块。更多业务已有规划,正在陆续接入中...QQAnimationKit所提供的能力为聊天彩蛋带来了极大的活跃度,除了点击率提高到10倍以外,好评率也很多,收获了很多赞赏。以这两天QQ聊天下雪彩蛋为例。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。