iOS 仿qq消息拖动动画(swift 版)

设计思路:

  1. 根据 titleLabel 的宽度计算 button的宽度
  2. 给小圆圈 添加手势
  3. 绘制拖动的贝塞尔曲线
  4. 添加炸裂效果

效果展示:

123.gif

使用:

func setBtn()  {
    //设置粘性的最长距离
    //小球的背景颜色
    //字体的颜色
    //距离超多多长, 可炸裂
    //位置
    let qqButton = QQBtn(buttonOption: QQButtonOptions(distance: 150.0, buttonBackColor: UIColor.magenta, titleColor: UIColor.white, disappearDistance: 200.0, center: CGPoint(x: self.bounds.width - 50, y: 20)))
    qqButton.count = String(arc4random() % 1000)
    contentView.insertSubview(qqButton, at: 0)
    
}

代码展示
1.计算 button 的宽度

let myString: NSString = count as NSString
let size: CGSize = myString.size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 17.0)]);            backgroundColor = option.buttonBackColor
self.bounds.size = CGSize(width: size.width + 10, height: size.height)

layer.cornerRadius = size.height / 2.0
layer.masksToBounds = true
  1. 添加手势, 以及让 button 随手指的移动
let tap = UITapGestureRecognizer(target: self, action: #selector(tapBootm))
self.addGestureRecognizer(tap)

//MARK:--- 手势拖动的操作
extension QQBtn{

//开始移动的时候, 记录初始位置
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    //记录按钮的初始状态
    btnSuperview = self.superview
    
    rect = self.convert(self.bounds, to: keyWindow)
    
}

//让小圆圈随着 手势拖动 移动
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?){
    for touch: AnyObject in touches {
        let t: UITouch = touch as! UITouch
        //获取当前手势的中心点, 赋值给当前的控件
        self.center = t.location(in: keyWindow)
        keyWindow.addSubview(self)
        
        let x = rect.origin.x + rect.width / 2 - self.center.x
        let y = rect.origin.y + rect.height / 2 - self.center.y
        
        
        moveDistance = sqrt(x * x + y * y)
        scal = (option.distance - moveDistance) / option.distance
        if moveDistance > option.distance || scal < 0.2{
            shapeLayer.path = nil
            circleLayer.path = nil
        }else{
           
            setCircleLayer()
            setCirCle()
            
        }
        
    }
}

//松手的时候
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    
    //keyWindow 移除当前的
    guard moveDistance < option.disappearDistance else {
        setBoomImage(str: "move")
        
        return
    }
    self.circleLayer.path = nil
    self.shapeLayer.path = nil
    //重新添加到 cell 上
    UIView.animate(withDuration: 0.4, delay: 0.0, usingSpringWithDamping: 0.2, initialSpringVelocity: 0.0, options: [.allowUserInteraction,.beginFromCurrentState], animations: {
        //在 keyWindow上的位置
        self.center = CGPoint(x: self.rect.origin.x + self.rect.width / 2, y: self.rect.origin.y + self.rect.height / 2)
    }) { (finished) in
        //在父视图上的位置
        self.center = self.option.center
        self.btnSuperview?.addSubview(self)
        
    }

}

}

  1. 绘制拖动的效果
    两个圆之间的不规则的矩形的, 算法分析 http://blog.csdn.net/xieyupeng520/article/details/50374561
 func setCirCle() {
    var cosDigree: CGFloat!
    var sinDigree: CGFloat!
    
    let x1: CGFloat = self.center.x
    let y1:CGFloat = self.center.y
    let x2:CGFloat = rect.origin.x + rect.width / 2.0
    let y2:CGFloat = rect.origin.y + rect.height / 2.0
    let x3: Float = Float((x2 - x1) * (x2 - x1))
    let y3: Float = Float((y2 - y1) * (y2 - y1))
    let centerDistance: CGFloat = CGFloat(sqrtf(x3 + y3))
    if centerDistance == 0 {
        cosDigree = 1;
        sinDigree = 0;
    }else{
        cosDigree = (y2 - y1) / centerDistance
        sinDigree = (x2 - x1) / centerDistance
    }
    let r1:CGFloat =  self.bounds.height / 2 - 5
    let r2 = rect.height * scal / 2
    let pointA = CGPoint(x: x1 - r1 * cosDigree, y: y1 + r1 * sinDigree)
    let pointB = CGPoint(x: x1 + r1 * cosDigree, y: y1 - r1 * sinDigree)
    let pointD = CGPoint(x: x2 - r2 * cosDigree!, y: y2 + r2 * sinDigree)
    let pointC = CGPoint(x: x2 + r2 * cosDigree!, y: y2 - r2 * sinDigree)
    let pointO = CGPoint(x: pointA.x + (centerDistance / 2) * sinDigree, y: pointA.y + (centerDistance / 2) * cosDigree)
    let pointP = CGPoint(x: pointB.x + (centerDistance / 2) * sinDigree, y: pointB.y + (centerDistance / 2) * cosDigree)
    
    
    let be = UIBezierPath()
    be.move(to: pointA)

    be.addQuadCurve(to: pointD, controlPoint: pointO)
    be.addLine(to: pointC)
    be.addQuadCurve(to: pointB, controlPoint: pointP)
    
    shapeLayer.path = be.cgPath

}
  1. 添加爆炸效果
@objc func setBoomImage(str: String)  {
    
    self.isHidden = true
    let imageView = UIImageView(frame: self.frame)
    
    let imageArray = NSMutableArray(capacity: 2)
    for i in 1..<5 {
        let image = UIImage(named: "unreadBomb_\(i)")
        imageArray.add(image!)
    }
    imageView.animationImages = imageArray as? [UIImage]
    imageView.animationDuration = 0.5
    imageView.animationRepeatCount = 1
    imageView.startAnimating()
    if str == "tap" {
        self.superview?.addSubview(imageView)
    }else{
        keyWindow.addSubview(imageView)
    }
    
    DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5) {
        imageView.removeFromSuperview()
    }
    
}

代码下载

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容