Skip to content
This repository has been archived by the owner on Aug 30, 2023. It is now read-only.

Commit

Permalink
Spring animations now take velocity into account when determining dur…
Browse files Browse the repository at this point in the history
…ation. (#56)

* Spring animations now take velocity into account when determining duration.

Prior to this change, spring animations were calculating their settling time prior to having set their initial velocity.

After this change, spring animations will calculate their settling time after having set the initial velocity.

* Add tests.
  • Loading branch information
jverkoey authored Nov 22, 2017
1 parent 47bee41 commit a8a40ea
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 6 deletions.
20 changes: 14 additions & 6 deletions src/private/CABasicAnimation+MotionAnimator.m
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,8 @@
spring.mass = timing.curve.data[MDMSpringMotionCurveDataIndexMass];
spring.stiffness = timing.curve.data[MDMSpringMotionCurveDataIndexTension];
spring.damping = timing.curve.data[MDMSpringMotionCurveDataIndexFriction];
spring.duration = timing.duration;

// This API is only available on iOS 9+
if ([spring respondsToSelector:@selector(settlingDuration)]) {
spring.duration = spring.settlingDuration;
} else {
spring.duration = timing.duration;
}
animation = spring;
break;
}
Expand Down Expand Up @@ -229,4 +224,17 @@ void MDMConfigureAnimation(CABasicAnimation *animation,
springAnimation.initialVelocity = absoluteInitialVelocity / displacement;
}
}

// Update the animation's duration to match the proposed settling duration.
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wpartial-availability"
if ([animation isKindOfClass:[CASpringAnimation class]]) {
CASpringAnimation *springAnimation = (CASpringAnimation *)animation;
#pragma clang diagnostic pop

// This API is only available on iOS 9+
if ([springAnimation respondsToSelector:@selector(settlingDuration)]) {
animation.duration = springAnimation.settlingDuration;
}
}
}
13 changes: 13 additions & 0 deletions tests/unit/InitialVelocityTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,19 @@ class InitialVelocityTests: XCTestCase {
}
}

func testVelocityInfluencesDuration() {
let velocity: CGFloat = 50
animate(from: 0, to: 100, withVelocity: velocity)

XCTAssertEqual(addedAnimations.count, 3)
addedAnimations.flatMap { $0 as? CASpringAnimation }.forEach { animation in
XCTAssertEqual(animation.duration, animation.settlingDuration,
"from: \(animation.fromValue!), "
+ "to: \(animation.toValue!), "
+ "withVelocity: \(velocity)")
}
}

private func animate(from: CGFloat, to: CGFloat, withVelocity velocity: CGFloat) {
let timing = MotionTiming(delay: 0,
duration: 0.7,
Expand Down

0 comments on commit a8a40ea

Please sign in to comment.