gpt4 book ai didi

ios - 如何将 CATransform3DTranslate 转换为 CGAffineTransform,以便它可以模仿轮播 View

转载 作者:行者123 更新时间:2023-11-28 07:24:41 27 4
gpt4 key购买 nike

我的问题是关于如何模仿这个 Carousel View Youtube video 只使用 UIView,而不是它的层或 CALayer,这意味着实际转换 UIView 本身。

我发现了一个堆栈溢出问题,它实际上能够转换一个 CATransform3D 到 CGAffineTransform。那是某个天才写的here作为答案,但我的问题有点独特。

您在下面看到的动画是使用 CALayer 创建的。我需要创建相同的动画,但要转换 UIView 而不是它的图层。

它应该是什么样子:

enter image description here

代码(使用图层创建动画):这需要一个图像卡,它是一个附有图像的 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
}
}

它目前的样子: enter image description here

所以基本上它很接近,但似乎应该被视为在前面的卡片和在后面<的卡片似乎存在缩放问题/em> 轮播。

为此,我所做的是使用 UIImageView 作为旋转木马的基础 View ,然后将更多 UIImageView 作为卡片添加到其中。所以现在我们正在尝试对 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
}
}

实际组成轮播的子图像添加了这个函数,它简单地通过我的 Assets 文件夹中名为 1...6 的图像的 for 循环。

代码:

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

目的:

这样做的目的是我想构建一个UI,可以在你看到的旋转卡片上取UIView,而一个CALayer不能添加一个UIView作为 subview 。它只能将 UIView 的层添加到它自己的层。所以要解决这个问题,我需要用 UIViews 而不是 CALayers 来实现这个动画。

最佳答案

我解决了看起来在最前面的 View 后面的 View 实际上捕获了所有的触摸,即使你在前面触摸一张卡片,后面的卡片也会阻止前面卡片的触摸。所以我做了一个可以计算的函数。哪些 View 在前面。然后禁用和启用触摸。就像当 2 张卡片堆叠在一起时,背面的卡片将阻止前面的卡片进行/用户交互。

代码:

   func DetermineFrontViews(view subview: UIView, angle angleOffset: CGFloat) {

let looped = Int(angleOffset / 360) // must round down to Int()
let loopSubtractingReset = CGFloat(360 * looped) // multiply 360 how ever many times we have looped

let finalangle = angleOffset - loopSubtractingReset

if (finalangle >= -70 && finalangle <= 70) || (finalangle >= 290) || (finalangle <= -260) {

print("In front of view")

if subview.isUserInteractionEnabled == false {
subview.isUserInteractionEnabled = true
}
} else {
print("Back of view")
if subview.isUserInteractionEnabled == true {
subview.isUserInteractionEnabled = false
}
}
}

我将其添加到旋转函数中,看看它是否可以跟踪第一张牌是在转盘的后面还是前面。

    if subview.layer.name == "1" {
DetermineFrontViews(view: subview, angle: angleOffset)
}

关于ios - 如何将 CATransform3DTranslate 转换为 CGAffineTransform,以便它可以模仿轮播 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56926035/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com