iOS 动画九:Layer Springs

UIKit vs. Core Animation springs

Layer Springs 动画与通过调用 UIKit 方法所创建的 Spring 动画有点不同,UIKit 方法创建的类似 spring 的动画过于简单,但作为对比 Core Animation 则呈现了一个看起来和感觉上更自然的物理模拟。

UIKit 以一种动态的方式调整所有其他变量,使系统在给定的持续时间内稳定下来,这就是为什么 UIKit spring 动画有时感觉有点勉强。UIKit 的动画有点跳跃了,看起来很不自然。

幸运的是,Core Animation 允许我们通过 CASpringAnimation 类为我们的 Layer 属性创建适当的 spring 动画。CASpringAnimation 在后台为 UIKit 创建了 spring动画,但是当我们调用它时,我们可以设置系统的各种变量,从而让动画自己稳定下来。这种方法的缺点是我们不能告诉动画它的持续时间是多少。系统会根据提供的变量,决定动画持续时间。

CASpringAnimation 动画可设置的几个属性:

  • damping: 作用在系统上的阻尼。
  • mass: 系统质量。
  • stiffness: 弹簧附加在重量上的硬度(刚度)。
    刚度可以取任何你喜欢的正值: 0 创建一个非常软的弹簧,100是默认值,每增加100,弹簧就会变得更硬。
  • initialVelocity: 初始速度。
举个钟摆例子 :
pendulum

如果没有摩擦力阻尼,它将一直来回摆动。

物理课上,老师在一直摆动的钟摆下面匀速拉动一张纸,摆动的钟摆将在纸上记录下运动轨迹,效果如下:

harmonic oscillator 谐波振荡器

现实中,因为有摩擦力,最终钟摆会停止在它的平衡点,即静止。

阻尼摆动

它的运动轨迹是这样的:

运动轨迹

钟摆终止运动的时长取决于几个因素:

  • damping: 空气阻力,机械阻力,等。
  • mass: 质量越重,摇摆时间越长。
  • stiffness: 振荡器的 “弹簧” 越硬,钟摆就越难摆动,系统就会稳定得越快。想象一下如果你在月球或木星上使用这个钟摆,在低重力和高重力条件下的运动和在地球上的运动是完全不同的。
  • initial velocity: 初速度。
示例代码:
 func animationDidStop(_ anim: CAAnimation,
                        finished flag: Bool) {
    print("animation did finish")

    guard let name = anim.value(forKey: "name") as? String else {
      return
    }

    if name == "form" {
      //form field found

      let layer = anim.value(forKey: "layer") as? CALayer
      anim.setValue(nil, forKey: "layer")

      // let pulse = CABasicAnimation(keyPath: "transform.scale")
     let pulse = CASpringAnimation(keyPath: "transform.scale")
      pulse.damping = 7.5// 阻尼大小,值越大,动画时间越短
      pulse.fromValue = 1.25
      pulse.toValue = 1.0
      // pulse.duration = 0.25
      pulse.duration = pulse.settlingDuration
      layer?.add(pulse, forKey: nil)
    }

    if name == "cloud" {
      if let layer = anim.value(forKey: "layer") as? CALayer {
        anim.setValue(nil, forKey: "layer")

        layer.position.x = -layer.bounds.width/2
        delay(seconds: 0.5) {
          self.animateCloud(layer: layer)
        }
      }
    }

  }

文本框提醒请输入动画

func textFieldDidEndEditing(_ textField: UITextField) {
        guard let text = textField.text else { return }
        if text.characters.count < 5 {
            // add animations here
            let jump = CASpringAnimation(keyPath: "position.y")
            jump.fromValue = textField.layer.position.y + 1.0
            jump.toValue = textField.layer.position.y
            jump.initialVelocity = 100.0
            jump.mass = 10.0
            jump.stiffness = 1500.0
            jump.damping = 50.0
            jump.duration = jump.settlingDuration
            textField.layer.add(jump, forKey: nil)
            
            textField.layer.borderWidth = 3.0
            textField.layer.borderColor = UIColor.clear.cgColor
            let flash = CASpringAnimation(keyPath: "borderColor")
            flash.damping = 7.0
            flash.stiffness = 200.0
            flash.fromValue = UIColor(red: 1.0, green: 0.27, blue: 0.0, alpha: 1.0).cgColor
            flash.toValue = UIColor.white.cgColor
            flash.duration = flash.settlingDuration
            textField.layer.add(flash, forKey: nil)
            
            textField.layer.cornerRadius = 5
        }
    }

demo下载

你可能感兴趣的:(iOS 动画九:Layer Springs)