iOS-QQ.badge

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
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明AI阅读 16,032评论 3 119
  • 淡淡的花园,影子走过,留下寂寞。夜色深重,有多少温存着翻涌的心,只是一墙之隔。在炊烟萦绕的晚风里,我打破了所有黄昏...
    心海的铆阅读 331评论 0 1
  • 木棉 又是一季木棉花开,它在春风中灼灼地盛放,风情万种,媚而不妖,很是鲜红得耀眼。花笑傲高枝,唯花独秀,红得热烈...
    映卿阅读 423评论 4 2
  • 举杯邀月共七夕, 对酒当歌独自逸。 志耀三湘烽火起, 诗情画意到期颐。
    志耀三湘阅读 426评论 0 0
  • 雪 一曲无声落九天 美不似人间 雪 千里江山起云烟 骋目亦无边 雪 万古文澜荡漪涟 亘古一诗篇
    关山野客阅读 506评论 0 1