Skip to content

Commit 5003a4d

Browse files
committed
Allow overshoot in interpolation
1 parent 4adfe62 commit 5003a4d

File tree

3 files changed

+23
-16
lines changed

3 files changed

+23
-16
lines changed

Sources/Interpolatable/CGPrimitives+Interpolatable.swift

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import Foundation
88
extension CGFloat: Interpolatable {
99
/// Interpolates between two scalar values.
1010
public func interpolate(to: CGFloat, progress: Double, easing: Easing) -> Self {
11-
return easing.calculate(d1: self, d2: to, g: progress)
11+
return easing.calculate(d1: self, d2: to, g: progress, clamp: false)
1212
}
1313
}
1414

@@ -25,21 +25,25 @@ extension CGPoint: Interpolatable {
2525
extension CGRect: Interpolatable {
2626
/// Interpolates between two rectangles component-wise.
2727
public func interpolate(to: CGRect, progress: Double, easing: Easing) -> Self {
28+
let interpolatedWidth = size.width.interpolate(to: to.size.width, progress: progress, easing: easing)
29+
let interpolatedHeight = size.height.interpolate(to: to.size.height, progress: progress, easing: easing)
2830
return CGRect(
2931
x: origin.x.interpolate(to: to.origin.x, progress: progress, easing: easing),
3032
y: origin.y.interpolate(to: to.origin.y, progress: progress, easing: easing),
31-
width: size.width.interpolate(to: to.size.width, progress: progress, easing: easing),
32-
height: size.height.interpolate(to: to.size.height, progress: progress, easing: easing)
33+
width: max(0, interpolatedWidth),
34+
height: max(0, interpolatedHeight)
3335
)
3436
}
3537
}
3638

3739
extension CGSize: Interpolatable {
3840
/// Interpolates between two sizes component-wise.
3941
public func interpolate(to: CGSize, progress: Double, easing: Easing) -> Self {
42+
let interpolatedWidth = width.interpolate(to: to.width, progress: progress, easing: easing)
43+
let interpolatedHeight = height.interpolate(to: to.height, progress: progress, easing: easing)
4044
return CGSize(
41-
width: width.interpolate(to: to.width, progress: progress, easing: easing),
42-
height: height.interpolate(to: to.height, progress: progress, easing: easing)
45+
width: max(0, interpolatedWidth),
46+
height: max(0, interpolatedHeight)
4347
)
4448
}
4549
}

Sources/Interpolatable/UIBezierPath+Interpolatable.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ extension UIBezierPath: Interpolatable {
7676
assert(!foundMistmatch, "UIBezierPath.interpolate: path elements type should be the same")
7777

7878
let interpolatedPath = Self(cgPath: CGPath.pathFromPathElements(interpolatedPathElements))
79-
interpolatedPath.lineWidth = lineWidth.interpolate(to: to.lineWidth, progress: progress, easing: easing)
79+
interpolatedPath.lineWidth = max(0, lineWidth.interpolate(to: to.lineWidth, progress: progress, easing: easing))
8080

8181
interpolatedPath.lineCapStyle = lineCapStyle
8282
assert(
@@ -90,8 +90,8 @@ extension UIBezierPath: Interpolatable {
9090
"UIBezierPath.interpolate: lineJoinStyle should be the same"
9191
)
9292

93-
interpolatedPath.miterLimit = miterLimit.interpolate(to: to.miterLimit, progress: progress, easing: easing)
94-
interpolatedPath.flatness = flatness.interpolate(to: to.flatness, progress: progress, easing: easing)
93+
interpolatedPath.miterLimit = max(0, miterLimit.interpolate(to: to.miterLimit, progress: progress, easing: easing))
94+
interpolatedPath.flatness = max(0, flatness.interpolate(to: to.flatness, progress: progress, easing: easing))
9595

9696
// TODO: implement line dash pattern interpolation
9797

Sources/Interpolatable/UIColor+Interpolatable.swift

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import UIKit
99

1010
extension UIColor: Interpolatable {
1111
// TODO: check alternative interpolations https://raphlinus.github.io/color/2021/01/18/oklab-critique.html
12+
private static func clamp01(_ value: CGFloat) -> CGFloat {
13+
return min(1, max(0, value))
14+
}
1215

1316
private func rgbaComponents() -> (CGFloat, CGFloat, CGFloat, CGFloat) {
1417
var r: CGFloat = 0
@@ -82,10 +85,10 @@ extension UIColor: Interpolatable {
8285
let (h2, s2, b2, a2) = to.hsbComponents()
8386

8487
return Self(
85-
hue: h1.interpolate(to: h2, progress: progress, easing: easing),
86-
saturation: s1.interpolate(to: s2, progress: progress, easing: easing),
87-
brightness: b1.interpolate(to: b2, progress: progress, easing: easing),
88-
alpha: a1.interpolate(to: a2, progress: progress, easing: easing)
88+
hue: Self.clamp01(h1.interpolate(to: h2, progress: progress, easing: easing)),
89+
saturation: Self.clamp01(s1.interpolate(to: s2, progress: progress, easing: easing)),
90+
brightness: Self.clamp01(b1.interpolate(to: b2, progress: progress, easing: easing)),
91+
alpha: Self.clamp01(a1.interpolate(to: a2, progress: progress, easing: easing))
8992
)
9093
}
9194

@@ -95,10 +98,10 @@ extension UIColor: Interpolatable {
9598
let (r2, g2, b2, a2) = to.rgbaComponents()
9699

97100
return Self(
98-
red: r1.interpolate(to: r2, progress: progress, easing: easing),
99-
green: g1.interpolate(to: g2, progress: progress, easing: easing),
100-
blue: b1.interpolate(to: b2, progress: progress, easing: easing),
101-
alpha: a1.interpolate(to: a2, progress: progress, easing: easing)
101+
red: Self.clamp01(r1.interpolate(to: r2, progress: progress, easing: easing)),
102+
green: Self.clamp01(g1.interpolate(to: g2, progress: progress, easing: easing)),
103+
blue: Self.clamp01(b1.interpolate(to: b2, progress: progress, easing: easing)),
104+
alpha: Self.clamp01(a1.interpolate(to: a2, progress: progress, easing: easing))
102105
)
103106
}
104107
}

0 commit comments

Comments
 (0)