Swift 动画 —— Facebook 点赞动画

新建一个Swift工程。然后首先要做的就是画出动画的曲线。

画曲线

新建一个CurvedView 类

  class CurvedView: UIView {
        override func draw(_ rect: CGRect) {
            
        }
    }

然后在viewDidLoad中创建一个CurvedView对象并且添加到view上。

   let curvedView = CurvedView(frame: view.frame)
        curvedView.backgroundColor = .yellow
        view.addSubview(curvedView)

接下来要画曲线,先画两个点后运行,发现是一条很细的直线。

  override func draw(_ rect: CGRect) {
            let path = UIBezierPath()
            
            path.move(to: CGPoint(x: 0, y: 200))
            let endPoint = CGPoint(x: 200, y: 200)
            path.addLine(to:endPoint)
            path.stroke()
            
        }

在这里插入图片描述
接下来要用到addCurve,在苹果官方文档中说到,此方法将当前点的三次贝塞尔曲线附加到终点参数指定的终点。这两个控制点定义了线段的曲率。看起来晕头转向的,写完代码后运行看的比较直观。

override func draw(_ rect: CGRect) {
            let path = UIBezierPath()
            
            path.move(to: CGPoint(x: 0, y: 200))
            let endPoint = CGPoint(x: 450, y: 200)
            path.lineWidth = 3
            let cp1 =  CGPoint(x: 100, y: 100)
            let cp2 =  CGPoint(x: 200, y: 300)
            path.addCurve(to: endPoint, controlPoint1: cp1, controlPoint2: cp2)
            path.stroke()
            
        }

在这里插入图片描述

2. 添加动画

把画的UIBezierPath分离成一个方法,这样就方便我们使用

func customPath() -> UIBezierPath {
    let path = UIBezierPath()
    
    path.move(to: CGPoint(x: 0, y: 200))
    let endPoint = CGPoint(x: 450, y: 200)
    path.lineWidth = 3
    let cp1 =  CGPoint(x: 100, y: 100)
    let cp2 =  CGPoint(x: 200, y: 300)
    path.addCurve(to: endPoint, controlPoint1: cp1, controlPoint2: cp2)
    path.stroke()
    return path
}

class CurvedView: UIView {
    override func draw(_ rect: CGRect) {
        let path = customPath()
        path.lineWidth = 3
        path.stroke()
        
    }
}

添加一张图片,并且将刚才的path赋值给animation,设置好动画时长等,然后将动画添加给图片。

        let imageView = UIImageView(image: UIImage(named: "heart"))
        imageView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
        let animation  = CAKeyframeAnimation(keyPath: "position")
        animation.path = customPath().cgPath
        animation.duration = 2
        animation.isRemovedOnCompletion = true
        animation.fillMode = .forwards
        animation.timingFunction = CAMediaTimingFunction(name: .easeOut)
        imageView.layer.add(animation, forKey: nil)
        view.addSubview(imageView)

接下来使用drand48给图片一个随机的大小。20 - 30

  let dimension = 20 + drand48() * 10
   imageView.frame = CGRect(x: 0, y: 0, width: dimension, height: dimension)

为view 添加一个手势

 view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))

每次点击都生成十个imageView。

   @objc func handleTap() {
        (0...10).forEach { (_) in
            generateAnimatedViews()
        }
    }
    func generateAnimatedViews() {
        
        let imageView = UIImageView(image: UIImage(named: "heart"))
        let dimension = 20 + drand48() * 10
        imageView.frame = CGRect(x: 0, y: 0, width: dimension, height: dimension)
        let animation  = CAKeyframeAnimation(keyPath: "position")
        animation.path = customPath().cgPath
        animation.duration = 2
        animation.isRemovedOnCompletion = true
        animation.fillMode = .forwards
        animation.timingFunction = CAMediaTimingFunction(name: .easeOut)
        imageView.layer.add(animation, forKey: nil)
        view.addSubview(imageView)
    }

到这里有个问题就是每个图片的path都是一样的,所以会叠加到一起,所以需要调整一下path。
在customPath方法中给cp1 和cp2添加随机性。

   let randomYShift = 200 +  drand48() * 300
    let cp1 =  CGPoint(x: 100, y: 100 -  randomYShift)
    let cp2 =  CGPoint(x: 200, y: 300 + randomYShift)

这里又发现了一个问题就是所有的图片都在一个X上面,这是因为它们的动画时长都一样,所以需要给动画时长页添加一点随机性。
在generateAnimatedViews方法中修改:

 animation.duration = 2 + drand48() * 3

为了图片随机,在generateAnimatedViews方法中修改:

 let image = drand48() > 0.5 ? UIImage(named: "heart") :  UIImage(named: "thumbs_up")
  let imageView =  UIImageView(image: image)

结束。完整代码如下:
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值