反转 UIView 动画并进行相反的 translationX 运动

Reversing a UIView animation and doing the opposite translationX movement

我有一个 UIImageView 动画 translationX: -250

我正在使用 autoreverse, .repeat 重复动画。

但是我希望发生的事情如下:

translationX: -250
translationX: 0
translationX: 250

并重复 - 基本上图像从 0 > -250 > 0 > +250 不断移动

class ViewController: UIViewController {

  private lazy var imageView: UIImageView = {
    let imageView = UIImageView(image: #imageLiteral(resourceName: "city_image_01"))
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.contentMode = .scaleAspectFill
    return imageView
  }()

  override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(imageView)
    NSLayoutConstraint.activate([
      imageView.topAnchor.constraint(equalTo: view.topAnchor),
      imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
      imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
      imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
    ])


    UIView.animate(withDuration: 20, delay: 0, options: [.autoreverse, .repeat, .curveEaseInOut], animations: {
      self.imageView.transform = .init(translationX: -250, y: 0)
    }, completion: { _ in })
  }
}

这应该可以帮助您获得想要的动画

        imageView.layer.anchorPoint = CGPoint(x: 0, y: 0.5)
        let animation = CABasicAnimation(keyPath: "position.x")
        animation.duration = 5
        animation.fromValue = 250
        animation.byValue = -500
        animation.autoreverses = true
        animation.repeatCount = .infinity
        self.imageView.layer.add(animation, forKey: "oscilatingAnimation")

希望对您有所帮助

您可以实现触发下一个动画阶段的基本状态机。

class ViewController: UIViewController {

  enum AnimationState {
    case stopped
    case started
    case finishing
  }

  var state: AnimationState = .stopped {
    didSet {
      switch state {
      case .stopped: runAnimation(.init(translationX: -250, y: 0), next: .started)
      case .started: runAnimation(.identity, next: .finishing)
      case .finishing: runAnimation(.init(translationX: 250, y: 0), next: .stopped)
      }
    }
  }

  private lazy var imageView: UIImageView = {
    let imageView = UIImageView(image: #imageLiteral(resourceName: "city_image_01"))
    imageView.translatesAutoresizingMaskIntoConstraints = false
    imageView.contentMode = .scaleAspectFill
    return imageView
  }()

  override func viewDidLoad() {
    super.viewDidLoad()

    view.addSubview(imageView)
    NSLayoutConstraint.activate([
      imageView.topAnchor.constraint(equalTo: view.topAnchor),
      imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
      imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
      imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
    ])

    state = .stopped
  }


  func runAnimation(_ transform: CGAffineTransform, next state: AnimationState) {
    UIView.animate(
      withDuration: 20,
      delay: 0,
      options: [.curveEaseInOut],
      animations: { self.imageView.transform = transform },
      completion: { _ in self.state = state }
    )
  }

}

如果稍微更改动画块,您应该会得到想要的效果:

// For the first animation, animate from 0 to -250 (no repeat)
UIView.animate(withDuration: 20, delay: 0, options: [ .curveEaseInOut], animations: {
    self.imageView.transform = .init(translationX: -250, y: 0)

}, completion: { _ in 
    // Once that's done, begin a repeating animation between -250 and 250
    UIView.animate(withDuration: 20, delay: 0, options: [.autoreverse, .repeat, .curveEaseInOut], animations: {
        self.imageView.transform = .init(translationX: 250, y: 0)

    }, completion: nil)
})