transform.scale 上的 CABasicAnimation 在 X 和 Y 轴上平移 CAShapeLayer
CABasicAnimation on transform.scale translates CAShapeLayer on the X & Y axis
我试图在按钮周围添加脉动效果,但是,我使用的代码翻译了 CAShapeLayer
并增加了它的大小。
如何在此动画期间仅增加 CAShapeLayer
的比例,同时保持其在视图中的位置不变?
我已将代码隔离到一个执行此动画的简单项目中,并且它仍在发生。
在此处查看视频中的效果:https://imgur.com/a/AbTtLKe
要对此进行测试:
- 创建一个新项目
- 在视图中心添加一个按钮
- Link 将其作为名称为 IBOutlet 的 viewControllers 代码文件
beginButton
这是我的代码:
let pulsatingLayer = CAShapeLayer()
override func viewDidLoad() {
super.viewDidLoad()
let circularPath = UIBezierPath(arcCenter: beginButton.center, radius: beginButton.bounds.midX, startAngle: -CGFloat.pi / 2, endAngle: 2 * .pi, clockwise: true)
pulsatingLayer.path = circularPath.cgPath
pulsatingLayer.strokeColor = UIColor.clear.cgColor
pulsatingLayer.lineWidth = 10
pulsatingLayer.fillColor = UIColor.red.cgColor
pulsatingLayer.lineCap = kCALineCapRound
view.layer.addSublayer(pulsatingLayer)
animatePulsatingLayer()
}
private func animatePulsatingLayer() {
let pulseAnimation = CABasicAnimation(keyPath: "transform.scale")
pulseAnimation.toValue = 1.5
pulseAnimation.duration = 1
pulseAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
pulseAnimation.autoreverses = true
pulseAnimation.repeatCount = Float.infinity
pulsatingLayer.add(pulseAnimation, forKey: "pulsing")
}
谢谢!
您需要阅读变换矩阵。 (任何关于 3D 计算机图形学的书籍都应该有一节涵盖它。)
缩放变换以当前原点为中心。因此,如果您的形状不以原点为中心,它将绘制在 towards 原点。要将形状向其自身的中心缩放,您需要执行以下操作:
创建身份转换
通过形状中心的 (-x, -y) 进行翻译
将所需的比例添加到转换中
添加一个 Translate by (x, y) 以将形状向后移动
将您的变换连接到图层的变换。
(我总是必须非常努力地思考才能把这些东西做对。我在当地时间 7:00 上午 7:00 之前在我的脑海中写下了上面的内容,没有足够的咖啡因。可能是完全正确,但应该给你想法。)
你的动画是相对于view
帧的原点的。
通过将圆形路径的中心更改为 CGPoint.zero
,您将获得一个以图层原点为中心的脉冲动画。然后将其添加到原点以按钮为中心的新 pulsatingView
,脉冲层以按钮为中心。
override func viewDidLoad() {
super.viewDidLoad()
let circularPath = UIBezierPath(arcCenter: CGPoint.zero, radius: beginButton.bounds.midX, startAngle: -CGFloat.pi / 2, endAngle: 2 * .pi, clockwise: true)
pulsatingLayer.path = circularPath.cgPath
pulsatingLayer.strokeColor = UIColor.clear.cgColor
pulsatingLayer.lineWidth = 10
pulsatingLayer.fillColor = UIColor.red.cgColor
pulsatingLayer.lineCap = kCALineCapRound
let pulsatingView = UIView(frame: .zero)
view.addSubview(pulsatingView)
view.bringSubview(toFront: beginButton)
// use Auto Layout to place the new pulsatingView relative to the button
pulsatingView.translatesAutoresizingMaskIntoConstraints = false
pulsatingView.leadingAnchor.constraint(equalTo: beginButton.centerXAnchor).isActive = true
pulsatingView.topAnchor.constraint(equalTo: beginButton.centerYAnchor).isActive = true
pulsatingView.layer.addSublayer(pulsatingLayer)
animatePulsatingLayer()
}
我试图在按钮周围添加脉动效果,但是,我使用的代码翻译了 CAShapeLayer
并增加了它的大小。
如何在此动画期间仅增加 CAShapeLayer
的比例,同时保持其在视图中的位置不变?
我已将代码隔离到一个执行此动画的简单项目中,并且它仍在发生。
在此处查看视频中的效果:https://imgur.com/a/AbTtLKe
要对此进行测试:
- 创建一个新项目
- 在视图中心添加一个按钮
- Link 将其作为名称为 IBOutlet 的 viewControllers 代码文件
beginButton
这是我的代码:
let pulsatingLayer = CAShapeLayer()
override func viewDidLoad() {
super.viewDidLoad()
let circularPath = UIBezierPath(arcCenter: beginButton.center, radius: beginButton.bounds.midX, startAngle: -CGFloat.pi / 2, endAngle: 2 * .pi, clockwise: true)
pulsatingLayer.path = circularPath.cgPath
pulsatingLayer.strokeColor = UIColor.clear.cgColor
pulsatingLayer.lineWidth = 10
pulsatingLayer.fillColor = UIColor.red.cgColor
pulsatingLayer.lineCap = kCALineCapRound
view.layer.addSublayer(pulsatingLayer)
animatePulsatingLayer()
}
private func animatePulsatingLayer() {
let pulseAnimation = CABasicAnimation(keyPath: "transform.scale")
pulseAnimation.toValue = 1.5
pulseAnimation.duration = 1
pulseAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
pulseAnimation.autoreverses = true
pulseAnimation.repeatCount = Float.infinity
pulsatingLayer.add(pulseAnimation, forKey: "pulsing")
}
谢谢!
您需要阅读变换矩阵。 (任何关于 3D 计算机图形学的书籍都应该有一节涵盖它。)
缩放变换以当前原点为中心。因此,如果您的形状不以原点为中心,它将绘制在 towards 原点。要将形状向其自身的中心缩放,您需要执行以下操作:
创建身份转换 通过形状中心的 (-x, -y) 进行翻译 将所需的比例添加到转换中 添加一个 Translate by (x, y) 以将形状向后移动
将您的变换连接到图层的变换。
(我总是必须非常努力地思考才能把这些东西做对。我在当地时间 7:00 上午 7:00 之前在我的脑海中写下了上面的内容,没有足够的咖啡因。可能是完全正确,但应该给你想法。)
你的动画是相对于view
帧的原点的。
通过将圆形路径的中心更改为 CGPoint.zero
,您将获得一个以图层原点为中心的脉冲动画。然后将其添加到原点以按钮为中心的新 pulsatingView
,脉冲层以按钮为中心。
override func viewDidLoad() {
super.viewDidLoad()
let circularPath = UIBezierPath(arcCenter: CGPoint.zero, radius: beginButton.bounds.midX, startAngle: -CGFloat.pi / 2, endAngle: 2 * .pi, clockwise: true)
pulsatingLayer.path = circularPath.cgPath
pulsatingLayer.strokeColor = UIColor.clear.cgColor
pulsatingLayer.lineWidth = 10
pulsatingLayer.fillColor = UIColor.red.cgColor
pulsatingLayer.lineCap = kCALineCapRound
let pulsatingView = UIView(frame: .zero)
view.addSubview(pulsatingView)
view.bringSubview(toFront: beginButton)
// use Auto Layout to place the new pulsatingView relative to the button
pulsatingView.translatesAutoresizingMaskIntoConstraints = false
pulsatingView.leadingAnchor.constraint(equalTo: beginButton.centerXAnchor).isActive = true
pulsatingView.topAnchor.constraint(equalTo: beginButton.centerYAnchor).isActive = true
pulsatingView.layer.addSublayer(pulsatingLayer)
animatePulsatingLayer()
}