Skip to content

Instantly share code, notes, and snippets.

@matt-curtis
Last active December 22, 2020 20:47
Show Gist options
  • Save matt-curtis/9a9d2ca80a9637f49ba59d702bc7ab96 to your computer and use it in GitHub Desktop.
Save matt-curtis/9a9d2ca80a9637f49ba59d702bc7ab96 to your computer and use it in GitHub Desktop.
CALayer.shadowPath and CALayer.path don't overshoot when spring animated.

Playground demonstrating CALayer.shadowPath's failure to overshoot when spring animated.

import UIKit
import PlaygroundSupport
class View: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
layer.shadowOpacity = 1
layer.shadowColor = UIColor.black.cgColor
layer.shadowOffset = .zero
layer.shadowRadius = 5
let startPath = UIBezierPath(
roundedRect: CGRect(
x: 75, y: 75,
width: 250, height: 250
),
byRoundingCorners: .allCorners,
cornerRadii: CGSize(width: 50, height: 50)
).cgPath
layer.shadowPath = startPath
let endPath = UIBezierPath(
roundedRect: CGRect(
x: 150, y: 150,
width: 100, height: 100
),
byRoundingCorners: .allCorners,
cornerRadii: CGSize(width: 25, height: 25)
).cgPath
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
let springAnimation = CASpringAnimation(keyPath: "shadowPath")
springAnimation.duration = springAnimation.settlingDuration
springAnimation.damping = 1
springAnimation.fromValue = startPath
springAnimation.toValue = endPath
self.layer.add(springAnimation, forKey: nil)
CATransaction.begin()
CATransaction.disableActions()
self.layer.shadowPath = endPath
CATransaction.commit()
}
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
let backgroundView = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
backgroundView.backgroundColor = .white
let shadowOnlyView = View(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
backgroundView.addSubview(shadowOnlyView)
PlaygroundPage.current.liveView = backgroundView

(This is a deviation from the main issue, but there's also an issue where CABasicAnimation.byValue and CABasicAnimation.isAdditive are ignored when animating CGPath properties. When UIViewPropertyAnimator generates animations, they're additive by default, so this gap prevents proper support for UIViewPropertyAnimator-based animations of path properties. This issue is not demonstrated here, though — none of the code below makes uses of additive animations.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment