iOS果冻效果(UIBezierPath实现)

作者: 王技术 | 来源:发表于2017-06-06 10:42 被阅读102次

    在网上看到的UI效果
    模仿写了Swift版本
    github地址
    效果图:

    gif.gif
    • View的使用:

            //创建
            let jellyView = HXJellyView()
            jellyView.frame = CGRect.init(x: 0, y: 0, width: Main_Width, height: Main_Height)
            //添加
            view.addSubview(jellyView)
    
    • 实现方法:

    • 控件包括两个子控件
      一个是红色Layer(CAShapeLayer)
      一个是紫色view
    • CAShapeLayer使用UIBezierPath描述
      紫色View作为UIBezierPath的控制点:


      示意图
    • 为控件添加手势
      紫色点根据手势的移动而移动
      紫色点位置改变,控制点也就被改变了,UIBezierPath就变了,进而改变了CAShapeLayer
    • 松开手后,使用UIView动画做弹性动画
    • 代码:

    • 监听属性,添加手势
        //创建属性(控制点的X和Y)
        dynamic var curveX : CGFloat = 0.0
        dynamic var curveY : CGFloat = 0.0
       //使用KVO监听这两个属性
        override init(frame: CGRect) {
            super.init(frame: frame)
            addObserver(self, forKeyPath: "curveX", options: NSKeyValueObservingOptions.new, context: nil)
            addObserver(self, forKeyPath: "curveY", options: NSKeyValueObservingOptions.new, context: nil)
            //添加手势
            let pan = UIPanGestureRecognizer.init(target: self, action: #selector(HXJellyView.handlePanAction))
            addGestureRecognizer(pan)
    }
    
    • 根据手势移动让紫色View执行动画,并改变监听属性
    func handlePanAction(){
            if isAnimating {
                return
            }
            //手势在移动的时候
            if pan.state == UIGestureRecognizerState.changed {
                //相对于初始触点位置
                let point = pan.translation(in: self)
                //让紫色点跟着手势走
                mHeight = point.y + Min_Height
               //改变监听属性的值
                curveX = point.x + Main_Width * 0.5
                curveY = mHeight > Min_Height ? mHeight : Min_Height
                curveView.frame = CGRect(x: curveX, y: curveY, width: 6, height: 6 )
            }
            //手松开的时候 做回弹动画
            else if pan.state == UIGestureRecognizerState.ended || pan.state == UIGestureRecognizerState.cancelled||pan.state == UIGestureRecognizerState.failed{
                isAnimating = true
                //松开手了,打开计时器,做弹性动画
                displayLink.isPaused = false
                UIView.animate(withDuration: 1.0,
                               delay: 0.0,
                               usingSpringWithDamping: 0.5,
                               initialSpringVelocity: 0,
                               options: UIViewAnimationOptions.curveEaseInOut,
                               animations: {
                                //让紫色点产生弹簧效果,路径跟着黄点走
                                self.curveView.frame = CGRect(x: Main_Width * 0.5 - 3.0, y: Min_Height, width: 6, height: 6)
                }, completion: { (finished) in
                    print(finished)
                    if finished{
                        self.displayLink.isPaused = true
                        self.isAnimating = false
                    }
                })
            }
        }
    
    • 手势移动的时候,监听属性被改变了,重新计算Path
        //改变path
        override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
            if keyPath == "curveX" || keyPath == "curveY" {
                let path = UIBezierPath.init()
                path.move(to: CGPoint(x: 0, y: 0))
                path.addLine(to: CGPoint(x: Main_Width, y: 0))
                path.addLine(to: CGPoint(x: Main_Width, y: Min_Height))
                path.addQuadCurve(to: CGPoint(x: 0, y: Min_Height), controlPoint: CGPoint(x: curveX, y: curveY))
                path.close()
                shapeLayer.path = path.cgPath
            }
    }
    
    • 松开手的时候,计时器被打开,紫色额View在做弹性动画,同时也要更改监听属性,让Path也相应作出改变
        //计算路径
        func calculatePath(){
            //动画开始时 presentation layer开始移动,原始layer隐藏,动画结束时,presentation layer从屏幕上移除,原始layer显示
            //所以移动的是presentation layer
            let layer = curveView.layer.presentation()
            curveX = (layer?.position.x)!
            curveY = (layer?.position.y)!
        }
    

    谢谢阅读
    有不合适的地方请指教
    喜欢请点个赞
    抱拳了!

    相关文章

      网友评论

        本文标题:iOS果冻效果(UIBezierPath实现)

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