Skip to content

Instantly share code, notes, and snippets.

@felixvisee
Last active August 29, 2015 14:25
Show Gist options
  • Save felixvisee/9d2ae41b41321b2a24c4 to your computer and use it in GitHub Desktop.
Save felixvisee/9d2ae41b41321b2a24c4 to your computer and use it in GitHub Desktop.
import CoreGraphics
public struct Interpolation<Value> {
private let interpolateFunc: (from: Value, to: Value, at: CGFloat) -> Value
public init(interpolate interpolateFunc: (from: Value, to: Value, at: CGFloat) -> Value) {
self.interpolateFunc = interpolateFunc
}
public func interpolate(from: Value, to: Value, at: CGFloat) -> Value {
return interpolateFunc(from: from, to: to, at: at)
}
}
public protocol Interpolatable {
typealias ValueType
func interpolation() -> Interpolation<ValueType>
}
extension Interpolation: Interpolatable {
public func interpolation() -> Interpolation<Value> {
return self
}
}
extension CGFloat: Interpolatable {
public func interpolation() -> Interpolation<CGFloat> {
return Interpolation { from, to, at in
return (to - from) * at + from
}
}
}
public struct Keyframe<Value> {
public var time: CGFloat
public var value: Value
public var interpolation: Interpolation<Value>
public init<I: Interpolatable where I.ValueType == Value>(time: CGFloat, value: Value, interpolation: I) {
self.time = time
self.value = value
self.interpolation = interpolation.interpolation()
}
}
public extension Keyframe {
public init(time: CGFloat, value: Value, interpolate: (from: Value, to: Value, at: CGFloat) -> Value) {
self.init(time: time, value: value, interpolation: Interpolation(interpolate: interpolate))
}
}
public extension Keyframe where Value: Interpolatable, Value.ValueType == Value {
public init(time: CGFloat, value: Value) {
self.init(time: time, value: value, interpolation: value)
}
}
public func inbetween<Value>(start start: Keyframe<Value>, end: Keyframe<Value>) -> (at: CGFloat) -> Value {
return { at in
return end.interpolation.interpolate(start.value, to: end.value, at: at)
}
}
do {
let start = Keyframe<CGFloat>(time: 0, value: 0)
let end = Keyframe<CGFloat>(time: 1, value: 1)
inbetween(start: start, end: end)(at: 0.5) // 0.5
}
do {
let start = Keyframe<CGFloat>(time: 0, value: 0)
let end = Keyframe<CGFloat>(time: 1, value: 1) { from, to, at in
return (to - from) * at / 2 + from
}
inbetween(start: start, end: end)(at: 0.5) // 0.25
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment