ios

iOS-QQ.badge

2018-10-25  本文已影响0人  NiSY

1. 拆分

① 拖拽移动badge
② badge原位置留下一个相同center的圆,圆半径随拖拽距离增大而减小
③ 两圆之间有一条牵引线,线的腰部随拖拽距离增大而收窄
④ 拖动距离小于某值,松开badge,badge返回原位置,有一个抖动和缩放动画
⑤ 拖动距离大于某值,badge消失

2. 关键动画实现

大圆小圆.001.jpeg

dis(拖动距离)是影响动画表现的关键参数:

let dis = sqrtf(powf(Float(circleCenter.x - badgeCenter.x), 2) + powf(Float(circleCenter.y - badgeCenter.y), 2))

根据β角三角函数结合半径,求出ABCD四点坐标

let cos = Float(badgeCenter.y - circleCenter.y) / dis
let sin = Float(badgeCenter.x - circleCenter.x) / dis
let circlePointA = CGPoint(x: circleCenter.x - CGFloat(cirlceR * cos) , y: circleCenter.y + CGFloat(cirlceR * sin))
let circlePointB = CGPoint(x: circleCenter.x + CGFloat(cirlceR * cos) , y: circleCenter.y - CGFloat(cirlceR * sin))
let badgePointC = CGPoint(x: badgeCenter.x + CGFloat(badgeR * cos), y: badgeCenter.y - CGFloat(badgeR * sin))
let badgePointD = CGPoint(x: badgeCenter.x - CGFloat(badgeR * cos), y: badgeCenter.y + CGFloat(badgeR * sin))

选择指数函数来表现腰部随距离拉长而收窄的效果

let controlPointArgument: Float = powf(0.1, dis / 200)
let circlePointMutativeA = CGPoint(x: circleCenter.x - CGFloat(cirlceR * cos * controlPointArgument) , y: circleCenter.y + CGFloat(cirlceR * sin * controlPointArgument))
let circlePointMutativeB = CGPoint(x: circleCenter.x + CGFloat(cirlceR * cos * controlPointArgument) , y: circleCenter.y - CGFloat(cirlceR * sin * controlPointArgument))

o&p点为贝塞尔曲线的控制点

let pointO = CGPoint(x: circlePointMutativeA.x + CGFloat(dis / 2 * sin), y: circlePointMutativeA.y + CGFloat(dis / 2 * cos))
let pointP = CGPoint(x: circlePointMutativeB.x + CGFloat(dis / 2 * sin), y: circlePointMutativeB.y + CGFloat(dis / 2 * cos))

最后使用CAShapeLayer绘制图形

let path = UIBezierPath()
path.move(to: circlePointA)
path.addLine(to: circlePointB)
path.addQuadCurve(to: badgePointC, controlPoint: pointP)
path.addLine(to: badgePointD)
path.addQuadCurve(to: circlePointA, controlPoint: pointO)
path.close()
shapeLayer.path = path.cgPath

抖动动画通过UIView动画实现,调用函数前需要把badge调整到合适位置

badgeView.center = CGPoint(x: circleCenter.x - CGFloat(50 * sin), y: circleCenter.y - CGFloat(50 * cos))
UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 0.2, initialSpringVelocity: 10, options: [], animations: {[weak self] in
            if let strongSelf = self {
                strongSelf.badgeView.center = strongSelf.redCircle.center
            }
        }) { (finished) in
        }

最后再加上一些简单的消失复位逻辑判断。


demo.gif
上一篇 下一篇

猜你喜欢

热点阅读