美文网首页
iOS 仿qq消息拖动动画(swift 版)

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

作者: e40c669177be | 来源:发表于2017-12-05 11:37 被阅读78次

    设计思路:

    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()
        }
        
    }
    

    代码下载

    相关文章

      网友评论

          本文标题:iOS 仿qq消息拖动动画(swift 版)

          本文链接:https://www.haomeiwen.com/subject/blqbmxtx.html