Реверс анимации UIView и выполнение противоположного движения translationX - PullRequest
0 голосов
/ 26 мая 2020

У меня есть 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 })
  }
}

Ответы [ 3 ]

1 голос
/ 26 мая 2020

Вы можете реализовать базовый c конечный автомат, который запускает следующий этап анимации.

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

}
1 голос
/ 26 мая 2020

Это должно помочь вам добиться той анимации, которую вы пытаетесь получить

        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")

enter image description here

Надеюсь, это поможет

0 голосов
/ 27 мая 2020

Если вы немного измените блок анимации, вы должны получить тот эффект, который вам нужен:

//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: {_ in}
      )
)
...