Я никогда не видел приложение «Behance», но, наверное, вы спрашиваете, как анимировать бесшовное мозаичное фоновое изображение на экране бесконечно, например:
( Узор Эвана Эккарда. )
Я использовал для анимации длительность анимации 1 секунду, но вы, вероятно, хотите, чтобы в реальном приложении она была намного длиннее.
Вы не должны использовать таймер для этого. Базовая анимация может выполнить анимацию за вас, а анимация будет более плавной и эффективной. (Вы можете подумать, что Core Animation выполняет анимацию, поскольку вы используете UIView
анимацию, но я считаю, что при анимации представления прокрутки contentOffset
не не использует Core Animation, потому что представление прокрутки должно вызывать его делегат scrollViewDidScroll
на каждом шаге анимации.)
Вы также не должны использовать представление прокрутки для этого. UIScrollView
существует, чтобы позволить пользователю прокручивать. Так как вы не позволяете пользователю прокручивать, вы не должны использовать UIScrollView
.
Вот как вы должны настроить фон:
Создание двух идентичных изображений (с номерами 0 и 1), показывающих одно и то же изображение. Убедитесь, что все изображения достаточно велики, чтобы заполнить экран.
Поместите левый край изображения 0 на левый край вашего корневого вида. Поместите левый край изображения 1 в правый край изображения 0. Поскольку каждый вид изображения достаточно большой, чтобы заполнить экран, изображение 1 будет полностью начинаться за правым краем экрана.
Просмотр анимированных изображений 0 х transform.translation.x
от 0 до -imageView.bounds.size.width
. Это заставит его скользить влево точно на его собственную ширину, поэтому, когда анимация достигает своего конца, правый край изображения 0 находится у левого края экрана (и, таким образом, изображение 0 полностью выходит за левый край экрана). ). Установите для анимации repeatCount
значение .infinity
.
Добавьте ту же анимацию к виду изображения 1. Таким образом, вид изображения 1 появляется на экране, когда вид изображения 0 покидает его, точно покрывая пиксели, отображаемые при анимации вида изображения 0.
Две анимации заканчиваются в одно и то же время. Когда они заканчиваются, вид изображения 1 находится именно там, где вид изображения 0 был в начале. Так как обе анимации настроены на бесконечное повторение, они сразу начинают все сначала. Когда анимация просмотра изображения 0 начинается заново, просмотр изображения 0 мгновенно возвращается в исходное положение, в котором заканчивается просмотр изображения 1. Поскольку оба изображения показывают одно и то же изображение, пиксели на экране не меняются. Это делает цикл анимации бесшовным.
Вот мой код:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
for imageView in imageViews {
imageView.image = patternImage
imageView.contentMode = .scaleToFill
view.addSubview(imageView)
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let bounds = view.bounds
let patternSize = patternImage.size
// Scale the image up if necessary to be at least as big as the screen on both axes.
// But make sure scale is at least 1 so I don't shrink the image if it's larger than the screen.
let scale = max(1 as CGFloat, bounds.size.width / patternSize.width, bounds.size.height / patternSize.height)
let imageFrame = CGRect(x: 0, y: 0, width: scale * patternSize.width, height: scale * patternSize.height)
for (i, imageView) in imageViews.enumerated() {
imageView.frame = imageFrame.offsetBy(dx: CGFloat(i) * imageFrame.size.width, dy: 0)
let animation = CABasicAnimation(keyPath: "transform.translation.x")
animation.fromValue = 0
animation.toValue = -imageFrame.size.width
animation.duration = 1
animation.repeatCount = .infinity
animation.timingFunction = CAMediaTimingFunction(name: .linear)
// The following line prevents iOS from removing the animation when the app goes to the background.
animation.isRemovedOnCompletion = false
imageView.layer.add(animation, forKey: animation.keyPath)
}
}
private let imageViews: [UIImageView] = [.init(), .init()]
private let patternImage = #imageLiteral(resourceName: "pattern")
}