Created
March 7, 2017 20:50
-
-
Save swillits/2cf93b846e6fa863bcae4cb03b99d8fd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import CoreGraphics | |
/* | |
Usage: | |
Interpolate(.linear).between(x, and: y, progress: progress) // progress is 0 to 1 | |
*/ | |
enum InterpolationCurveType { | |
case linear | |
} | |
func Interpolate(_ curveType: InterpolationCurveType) -> InterpolationCurve { | |
switch curveType { | |
case .linear: | |
return LinearInterpolation | |
} | |
} | |
struct InterpolationCurve { | |
let valueForProgress: (_ progress: Double) -> Double | |
init(_ block: @escaping (_ progress: Double) -> Double) { | |
valueForProgress = block | |
} | |
} | |
let LinearInterpolation = InterpolationCurve { (_ progress: Double) -> Double in | |
return progress | |
} | |
extension InterpolationCurve { | |
func between(_ from: Double, and to: Double, progress: Double) -> Double { | |
let cv = valueForProgress(progress) | |
return (1.0 - cv) * from + cv * to | |
} | |
func between(_ from: Float, and to: Float, progress: Double) -> Float { | |
let cv = valueForProgress(progress) | |
return Float(1.0 - cv) * from + Float(cv) * to | |
} | |
func between(_ from: CGFloat, and to: CGFloat, progress: Double) -> CGFloat { | |
let cv = valueForProgress(progress) | |
return CGFloat(1.0 - cv) * from + CGFloat(cv) * to | |
} | |
func between(_ from: CGPoint, and to: CGPoint, progress: Double) -> CGPoint { | |
let x = between(from.x, and: to.x, progress: progress) | |
let y = between(from.y, and: to.y, progress: progress) | |
return CGPoint(x: x, y: y) | |
} | |
func between(_ from: CGSize, and to: CGSize, progress: Double) -> CGSize { | |
let width = between(from.width, and: to.width, progress: progress) | |
let height = between(from.height, and: to.height, progress: progress) | |
return CGSize(width: width, height: height) | |
} | |
func between(_ from: CGRect, and to: CGRect, progress: Double) -> CGRect { | |
let origin = between(from.origin, and: to.origin, progress: progress) | |
let size = between(from.size, and: to.size, progress: progress) | |
return CGRect(origin: origin, size: size) | |
} | |
func between(_ from: CGAffineTransform, and to: CGAffineTransform, progress: Double) -> CGAffineTransform { | |
let tx1 = from.translationX | |
let tx2 = to.translationX | |
let tx = between(tx1, and: tx2, progress: progress) | |
let ty1 = from.translationY | |
let ty2 = to.translationY | |
let ty = between(ty1, and: ty2, progress: progress) | |
let sx1 = from.scaleX | |
let sx2 = to.scaleX | |
let sx = between(sx1, and: sx2, progress: progress) | |
let sy1 = from.scaleY | |
let sy2 = to.scaleY | |
let sy = between(sy1, and: sy2, progress: progress) | |
let deg1 = from.rotationDegrees | |
let deg2 = to.rotationDegrees | |
let deg = between(deg1, and: deg2, progress: progress) | |
return CGAffineTransform.makeCorrectly(tx, ty, sx, sy, deg) | |
} | |
} | |
extension CGAffineTransform { | |
var translationX: CGFloat { return tx } | |
var translationY: CGFloat { return ty } | |
var scaleX: CGFloat { return sqrt(a * a + c * c) } | |
var scaleY: CGFloat { return sqrt(b * b + d * d) } | |
var rotationDegrees: CGFloat { return (atan2(b, a) * 180) / CGFloat(M_PI_2) } | |
/// `CGAffineTransformMake()`, The Right Way™ | |
/// | |
/// - parameter tx: translation on x axis. | |
/// - parameter ty: translation on y axis. | |
/// - parameter sx: scale factor for width. | |
/// - parameter sy: scale factor for height. | |
/// - parameter deg: degrees. | |
static func makeCorrectly(_ tx: CGFloat, _ ty: CGFloat, _ sx: CGFloat, _ sy: CGFloat, _ deg: CGFloat) -> CGAffineTransform { | |
let translationTransform = CGAffineTransform(translationX: tx, y: ty) | |
let scaleTransform = CGAffineTransform(scaleX: sx, y: sy) | |
let rotationTransform = CGAffineTransform(rotationAngle: deg * CGFloat(M_PI_2) / 180.0) | |
return translationTransform.concatenating(scaleTransform).concatenating(rotationTransform) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment