Мой вопрос касается того, как имитировать этот вид карусели Youtube видео только с использованием UIView, а не его слоя или CALayer , что означает на самом деле преобразование UIViews в себя.
Я нашел вопрос переполнения стека, который на самом деле способен конвертировать CATransform3D в CGAffineTransform .Это было написано неким гением здесь в качестве ответа, но моя проблема немного уникальна.
Анимация, которую вы видите ниже, использует CALayer для создания.Мне нужно создать ту же анимацию, но трансформировать UIView вместо ее слоя.
Как это должно выглядеть:
Код (Создает анимацию с использованием слоев): Это берет карту изображения, которая является CALayer () с прикрепленным к ней изображением, и преобразует, что помещает ее в карусель изображений.
Примечание: turnCarousel () также вызывается, когда пользователь перемещается, перемещая / анимируя карусель.
let transformLayer = CATransformLayer()
func turnCarousel() {
guard let transformSubLayers = transformLayer.sublayers else {return}
let segmentForImageCard = CGFloat(360 / transformSubLayers.count)
var angleOffset = currentAngle
for layer in transformSubLayers {
var transform = CATransform3DIdentity
transform.m34 = -1 / 500
transform = CATransform3DRotate(transform, degreeToRadians(deg: angleOffset), 0, 1, 0)
transform = CATransform3DTranslate(transform, 0, 0, 175)
CATransaction.setAnimationDuration(0)
layer.transform = transform
angleOffset += segmentForImageCard
}
}
Что это выглядит в данный моментКак:
Так что в основном это близко, но кажется, что есть проблема с масштабированием с картами, которые должны рассматриваться как вспереди и карты сзади карусели.
Для этого я использовал UIImageView в качестве базового вида для карусели, а затем добавил еще UIImageViews в качествекарты к нему.Итак, теперь мы пытаемся выполнить преобразование UIImageView / UIView
Код:
var carouselTestView = UIImageView()
func turnCarouselTestCarousel() {
let segmentForImageCard = CGFloat(360 / carouselTestView.subviews.count)
var angleOffset = currentAngleTestView
for subview in carouselTestView.subviews {
var transform2 = CATransform3DIdentity
transform2.m34 = -1 / 500
transform2 = CATransform3DRotate(transform2, degreeToRadians(deg: angleOffset), 0, 1, 0)
transform2 = CATransform3DTranslate(transform2, 0, 0, 175)
CATransaction.setAnimationDuration(0)
// m13, m23, m33, m43 are not important since the destination is a flat XY plane.
// m31, m32 are not important since they would multiply with z = 0.
// m34 is zeroed here, so that neutralizes foreshortening. We can't avoid that.
// m44 is implicitly 1 as CGAffineTransform's m33.
let fullTransform: CATransform3D = transform2
let affine = CGAffineTransform(a: fullTransform.m11, b: fullTransform.m12, c: fullTransform.m21, d: fullTransform.m22, tx: fullTransform.m41, ty: fullTransform.m42)
subview.transform = affine
angleOffset += segmentForImageCard
}
}
добавлено вспомогательное изображение, которое фактически составляет карусельс этой функцией, которая просто проходит цикл for с именем 1 ... 6 в моей папке ресурсов.
Код:
func CreateCarousel() {
carouselTestView.frame.size = CGSize(width: self.view.frame.width, height: self.view.frame.height / 2.9)
carouselTestView.center = CGPoint(self.view.frame.width * 0.5, self.view.frame.height * 0.5)
carouselTestView.alpha = 1.0
carouselTestView.backgroundColor = UIColor.clear
carouselTestView.isUserInteractionEnabled = true
self.view.insertSubview(carouselTestView, at: 0)
for i in 1 ... 6 {
addImageCardTestCarousel(name: "\(i)")
}
// Set the carousel for the first time. So that now we can see it like an actual carousel animation
turnCarouselTestCarousel()
let panGestureRecognizerTestCarousel = UIPanGestureRecognizer(target: self, action: #selector(self.performPanActionTestCarousel(recognizer:)))
panGestureRecognizerTestCarousel.delegate = self
carouselTestView.addGestureRecognizer(panGestureRecognizerTestCarousel)
}
Функция addImageCardTestCarousel находится здесь:
Код:
func addImageCardTestCarousel(name: String) {
let imageCardSize = CGSize(width: carouselTestView.frame.width / 2, height: carouselTestView.frame.height)
let cardPanel = UIImageView()
cardPanel.frame.size = CGSize(width: imageCardSize.width, height: imageCardSize.height)
cardPanel.frame.origin = CGPoint(carouselTestView.frame.size.width / 2 - imageCardSize.width / 2 , carouselTestView.frame.size.height / 2 - imageCardSize.height / 2)
guard let imageCardImage = UIImage(named: name) else {return}
cardPanel.image = imageCardImage
cardPanel.contentMode = .scaleAspectFill
cardPanel.layer.masksToBounds = true
cardPanel.layer.borderColor = UIColor.white.cgColor
cardPanel.layer.borderWidth = 1
cardPanel.layer.cornerRadius = cardPanel.frame.height / 50
carouselTestView.addSubview(cardPanel)
}
Цель:
Цель этого в том, что я хочусоздать пользовательский интерфейс, который может использовать UIViews на вращающихся картах, которые вы видите, и CALayer не может добавить UIView в качестве подпредставления.Он может только добавить слой UIView к своему собственному слою.Поэтому для решения этой проблемы мне нужно на самом деле добиться этой анимации с помощью UIViews, а не CALayers.