这次是一个Loader

前几天在食堂排队时刷tweet,然后见看到了这个东西http://t.co/sUuYTeKOzp。觉得十分有趣,就想着去实现一下,于是就有了这篇文章。先看效果图。

spinnerloader

思路

整体来看有八个固定的点,一个动态的点,然后整体效果是由三个动画合成的:1.动态点旋转动画。2.动态点与固定点接触时,固定点半径的放大和缩小动画。3.动态点与固定点接触与分解时的”粘连“动画。

做法

  • 首先定义几个东西
    • 大圆的圆心(bigCircleCneterX, bigCircleCenterY)。
    • 大圆的半径raduis。
    • 固定点的半径circleRaduis。
    • 动态点的半径moveRaduis。
    • 动态点每次移动的角度STEP。
    • 固定点半径的增益长度ADDITION_LENGTH。
    • 动态点的圆心与固定点圆心的距离distance。动态点是否与固定点相交:
1
2
3
4
private boolean isIntersect(CirclePoint a, CirclePoint b) {
float distance = (float)Math.sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y));
return distance < (a.raduis + b.raduis);
}
  • 然后画八个固定点,只需要确定圆心和半径即可
1
p.x = getPaddingLeft() + bigCircleCenterX + (float)Math.cos(Math.toRadians(45 * i)) * raduis; p.y = getPaddingTop() + bigCircleCenterY + (float)Math.sin(Math.toRadians(45 * i)) * raduis;
  • 动态点的绘制
1
2
3
p.x = bigCircleCenterX + (float)Math.cos(Math.toRadians(angle)) * raduis;
p.y = bigCircleCenterY + (float)Math.sin(Math.toRadians(angle)) * raduis;
angle = angle + STEP;
  • 固定点与动态点相交时的半径变化
    当相交时半径开始变化,二者的圆心离得越近固定点的半径增益越大。利用前面提到的判断是否相交的函数,如果相交则半径增益的计算规则为:
    srealRaduis = circleRaduis + (1 - distance / (circleRaduis + moveRaduis))

  • 动态点与固定点接触与分解时的”粘连“动画
    这个效果与手Q 的红点消除效果差不多,都是用贝塞尔曲线做的。
    盗用两张图(图片来自http://isux.tencent.com/qq-mobile-off-duty.html):

要做出“粘连”的效果,关键是要计算出如图的p1 p2 p3 p4还有P5这几个点。p1-p4是两个圆的切点,p5这个点是贝塞尔曲线的控制点,这个里面我取的是固定点与动态点圆心连线的中点。具体怎么计算出p1-p4并绘制,我参考了这个项目https://github.com/chenupt/SpringIndicator

好了,到这里就介绍完了,附上源码地址GitHub