Skip to content

Instantly share code, notes, and snippets.

@matt-curtis
Last active December 22, 2020 20:47
Show Gist options
  • Select an option

  • Save matt-curtis/9a9d2ca80a9637f49ba59d702bc7ab96 to your computer and use it in GitHub Desktop.

Select an option

Save matt-curtis/9a9d2ca80a9637f49ba59d702bc7ab96 to your computer and use it in GitHub Desktop.

Revisions

  1. matt-curtis revised this gist Dec 22, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion 1.Info.md
    Original file line number Diff line number Diff line change
    @@ -1 +1 @@
    # Playground demonstrating `CALayer.shadowPath`'s failure to overshoot when animated.
    # Playground demonstrating `CALayer.shadowPath`'s failure to overshoot when spring animated.
  2. matt-curtis revised this gist Dec 22, 2020. 3 changed files with 1 addition and 2 deletions.
    1 change: 1 addition & 0 deletions 1.Info.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    # Playground demonstrating `CALayer.shadowPath`'s failure to overshoot when animated.
    File renamed without changes.
    2 changes: 0 additions & 2 deletions 1-Info.md → 3.Also.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1 @@
    # Playground demonstrating `CALayer.shadowPath`'s failure to overshoot when animated.

    *(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.)*
  3. matt-curtis revised this gist Dec 22, 2020. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion 1-Info.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,3 @@
    # Playground demonstrating `CALayer.shadowPath`'s failure to overshoot when animated.

    *(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 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.)*
  4. matt-curtis revised this gist Dec 22, 2020. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions 1-Info.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,3 @@
    # CALayer.shadowPath and CALayer.path don't overshoot when spring animated.
    # Playground demonstrating `CALayer.shadowPath`'s failure to overshoot when animated.

    This is a sidenote, but `CABasicAnimation.byValue` and `CABasicAnimation.isAdditive` are ignored when animating `CGPath`s (`path` or `shadowPath`).
    *(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)*
  5. matt-curtis revised this gist Dec 22, 2020. No changes.
  6. matt-curtis revised this gist Dec 22, 2020. 2 changed files with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions 1-Info.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    # CALayer.shadowPath and CALayer.path don't overshoot when spring animated.

    This is a sidenote, but `CABasicAnimation.byValue` and `CABasicAnimation.isAdditive` are ignored when animating `CGPath`s (`path` or `shadowPath`).
    File renamed without changes.
  7. matt-curtis created this gist Dec 22, 2020.
    69 changes: 69 additions & 0 deletions PathsDontOvershoot.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,69 @@
    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