如何防止 CABasicAnimation 缩放 UIView 中的所有内容?
How to prevent CABasicAnimation from scale all content inside UIView?
我写这个是为了将心跳动画应用到 CAShapeLayer,在这工作正常之后,我需要将它实现在 UIButton (btnTest) 后面而不缩放 UIButton 或任何其他内容。
@IBOutlet weak var btnTest: UIButton!
let btnLayer = CAShapeLayer()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
btnTest.layer.removeAllAnimations()
let ovalPath = UIBezierPath(arcCenter: CGPoint(x: btnTest.frame.midX, y: btnTest.frame.midY), radius: 100, startAngle: 0*(CGFloat.pi / 180), endAngle: 360*(CGFloat.pi / 180), clockwise: true)
btnLayer.path = ovalPath.cgPath
btnLayer.fillColor = UIColor.red.cgColor
btnLayer.contentsGravity = "center"
btnLayer.opacity = 0.3
self.view.layer.addSublayer(btnLayer)
let theAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
theAnimation.duration = 0.75
theAnimation.repeatCount = Float.infinity
theAnimation.autoreverses = true
theAnimation.fromValue = 1.0
theAnimation.toValue = 1.2
theAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
self.view.layer.add(theAnimation, forKey: nil)
}
这是这个结果gif
另一个解决方案是更改此行:
self.view.layer.add(theAnimation, forKey: nil)
对此:
btnLayer.add(theAnimation, forKey: nil)
结果是这样的:gif
解决这个问题的任何想法!
1- 首先制作心形,让 UIView
动起来,我们将其命名为 heartView
.
2- self.view.addsubview(heartView)
(self.view
可以随便改成parent)
3-制作一个名为heartButton
的不可见按钮并给它相同的框架heartView
4- self.view.addsubview(heartButton)
(self.view
可以改成任何你想要的parent)
5-启动heartView动画。
这里的关键点不是在动画视图上添加按钮,而是在它们的 parent 上添加按钮(self.view
这种情况)因为如果 button
位于心脏顶部并且心脏是动画的,按钮将采用动画。
希望对您有所帮助!
您想为您的 btnLayer
制作动画。它从错误的位置设置动画的原因可能是层的 anchorPoint
位于 0,0,它应该设置为 0.5, 0.5.
编辑:
实际上,我认为问题在于您将 btnLayer
放在哪里。您应该使它成为按钮视图层的子层,并为其提供一个作为按钮层边界的框架:
btnTest.layer.addSublayer(btnLayer)
btnLayer.frame = btnTest.layer.bounds
您可以这样做,只需将您的图层与缩放动画一起平移即可。为此,您需要创建一个 CAAnimationGroup。
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
btnTest.layer.removeAllAnimations()
let ovalPath = UIBezierPath(arcCenter: CGPoint(x: btnTest.frame.midX, y: btnTest.frame.midY), radius: 100, startAngle: 0*(CGFloat.pi / 180), endAngle: 360*(CGFloat.pi / 180), clockwise: true)
btnLayer.path = ovalPath.cgPath
btnLayer.fillColor = UIColor.red.cgColor
btnLayer.anchorPoint = CGPoint.init(x: 0.5, y: 0.5)
btnLayer.contentsGravity = "center"
btnLayer.opacity = 0.3
self.view.layer.addSublayer(btnLayer)
let theAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
theAnimation.fromValue = 1.0
theAnimation.toValue = 1.2
let theAnimationTranslationX = CABasicAnimation(keyPath: "transform.translation.x")
theAnimationTranslationX.fromValue = btnTest.bounds.minX
theAnimationTranslationX.toValue = btnTest.bounds.minX - 40
let theAnimationTranslationY = CABasicAnimation(keyPath: "transform.translation.y")
theAnimationTranslationY.fromValue = btnTest.bounds.minY
theAnimationTranslationY.toValue = btnTest.bounds.minY - 80
let animationGroup = CAAnimationGroup.init()
animationGroup.duration = 0.75
animationGroup.repeatCount = Float.infinity
animationGroup.autoreverses = true
animationGroup.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
animationGroup.animations = [theAnimation,theAnimationTranslationX,theAnimationTranslationY]
btnLayer.add(animationGroup, forKey: nil)
}
我写这个是为了将心跳动画应用到 CAShapeLayer,在这工作正常之后,我需要将它实现在 UIButton (btnTest) 后面而不缩放 UIButton 或任何其他内容。
@IBOutlet weak var btnTest: UIButton!
let btnLayer = CAShapeLayer()
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
btnTest.layer.removeAllAnimations()
let ovalPath = UIBezierPath(arcCenter: CGPoint(x: btnTest.frame.midX, y: btnTest.frame.midY), radius: 100, startAngle: 0*(CGFloat.pi / 180), endAngle: 360*(CGFloat.pi / 180), clockwise: true)
btnLayer.path = ovalPath.cgPath
btnLayer.fillColor = UIColor.red.cgColor
btnLayer.contentsGravity = "center"
btnLayer.opacity = 0.3
self.view.layer.addSublayer(btnLayer)
let theAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
theAnimation.duration = 0.75
theAnimation.repeatCount = Float.infinity
theAnimation.autoreverses = true
theAnimation.fromValue = 1.0
theAnimation.toValue = 1.2
theAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
self.view.layer.add(theAnimation, forKey: nil)
}
这是这个结果gif
另一个解决方案是更改此行:
self.view.layer.add(theAnimation, forKey: nil)
对此:
btnLayer.add(theAnimation, forKey: nil)
结果是这样的:gif
解决这个问题的任何想法!
1- 首先制作心形,让 UIView
动起来,我们将其命名为 heartView
.
2- self.view.addsubview(heartView)
(self.view
可以随便改成parent)
3-制作一个名为heartButton
的不可见按钮并给它相同的框架heartView
4- self.view.addsubview(heartButton)
(self.view
可以改成任何你想要的parent)
5-启动heartView动画。
这里的关键点不是在动画视图上添加按钮,而是在它们的 parent 上添加按钮(self.view
这种情况)因为如果 button
位于心脏顶部并且心脏是动画的,按钮将采用动画。
希望对您有所帮助!
您想为您的 btnLayer
制作动画。它从错误的位置设置动画的原因可能是层的 anchorPoint
位于 0,0,它应该设置为 0.5, 0.5.
编辑:
实际上,我认为问题在于您将 btnLayer
放在哪里。您应该使它成为按钮视图层的子层,并为其提供一个作为按钮层边界的框架:
btnTest.layer.addSublayer(btnLayer)
btnLayer.frame = btnTest.layer.bounds
您可以这样做,只需将您的图层与缩放动画一起平移即可。为此,您需要创建一个 CAAnimationGroup。
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
btnTest.layer.removeAllAnimations()
let ovalPath = UIBezierPath(arcCenter: CGPoint(x: btnTest.frame.midX, y: btnTest.frame.midY), radius: 100, startAngle: 0*(CGFloat.pi / 180), endAngle: 360*(CGFloat.pi / 180), clockwise: true)
btnLayer.path = ovalPath.cgPath
btnLayer.fillColor = UIColor.red.cgColor
btnLayer.anchorPoint = CGPoint.init(x: 0.5, y: 0.5)
btnLayer.contentsGravity = "center"
btnLayer.opacity = 0.3
self.view.layer.addSublayer(btnLayer)
let theAnimation = CABasicAnimation(keyPath: "transform.scale.xy")
theAnimation.fromValue = 1.0
theAnimation.toValue = 1.2
let theAnimationTranslationX = CABasicAnimation(keyPath: "transform.translation.x")
theAnimationTranslationX.fromValue = btnTest.bounds.minX
theAnimationTranslationX.toValue = btnTest.bounds.minX - 40
let theAnimationTranslationY = CABasicAnimation(keyPath: "transform.translation.y")
theAnimationTranslationY.fromValue = btnTest.bounds.minY
theAnimationTranslationY.toValue = btnTest.bounds.minY - 80
let animationGroup = CAAnimationGroup.init()
animationGroup.duration = 0.75
animationGroup.repeatCount = Float.infinity
animationGroup.autoreverses = true
animationGroup.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
animationGroup.animations = [theAnimation,theAnimationTranslationX,theAnimationTranslationY]
btnLayer.add(animationGroup, forKey: nil)
}