114 lines
3.2 KiB
Swift
114 lines
3.2 KiB
Swift
//
|
|
// Keyframe.swift
|
|
// lottie-swift
|
|
//
|
|
// Created by Brandon Withrow on 1/7/19.
|
|
//
|
|
|
|
import CoreGraphics
|
|
import Foundation
|
|
|
|
// MARK: - KeyframeData
|
|
|
|
/// A generic class used to parse and remap keyframe json.
|
|
///
|
|
/// Keyframe json has a couple of different variations and formats depending on the
|
|
/// type of keyframea and also the version of the JSON. By parsing the raw data
|
|
/// we can reconfigure it into a constant format.
|
|
final class KeyframeData<T> {
|
|
|
|
// MARK: Lifecycle
|
|
|
|
init(
|
|
startValue: T?,
|
|
endValue: T?,
|
|
time: AnimationFrameTime?,
|
|
hold: Int?,
|
|
inTangent: Vector2D?,
|
|
outTangent: Vector2D?,
|
|
spatialInTangent: Vector3D?,
|
|
spatialOutTangent: Vector3D?)
|
|
{
|
|
self.startValue = startValue
|
|
self.endValue = endValue
|
|
self.time = time
|
|
self.hold = hold
|
|
self.inTangent = inTangent
|
|
self.outTangent = outTangent
|
|
self.spatialInTangent = spatialInTangent
|
|
self.spatialOutTangent = spatialOutTangent
|
|
}
|
|
|
|
// MARK: Internal
|
|
|
|
enum CodingKeys: String, CodingKey {
|
|
case startValue = "s"
|
|
case endValue = "e"
|
|
case time = "t"
|
|
case hold = "h"
|
|
case inTangent = "i"
|
|
case outTangent = "o"
|
|
case spatialInTangent = "ti"
|
|
case spatialOutTangent = "to"
|
|
}
|
|
|
|
/// The start value of the keyframe
|
|
let startValue: T?
|
|
/// The End value of the keyframe. Note: Newer versions animation json do not have this field.
|
|
let endValue: T?
|
|
/// The time in frames of the keyframe.
|
|
let time: AnimationFrameTime?
|
|
/// A hold keyframe freezes interpolation until the next keyframe that is not a hold.
|
|
let hold: Int?
|
|
|
|
/// The in tangent for the time interpolation curve.
|
|
let inTangent: Vector2D?
|
|
/// The out tangent for the time interpolation curve.
|
|
let outTangent: Vector2D?
|
|
|
|
/// The spacial in tangent of the vector.
|
|
let spatialInTangent: Vector3D?
|
|
/// The spacial out tangent of the vector.
|
|
let spatialOutTangent: Vector3D?
|
|
|
|
var isHold: Bool {
|
|
if let hold = hold {
|
|
return hold > 0
|
|
}
|
|
return false
|
|
}
|
|
}
|
|
|
|
// MARK: Encodable
|
|
|
|
extension KeyframeData: Encodable where T: Encodable { }
|
|
|
|
// MARK: Decodable
|
|
|
|
extension KeyframeData: Decodable where T: Decodable { }
|
|
|
|
// MARK: DictionaryInitializable
|
|
|
|
extension KeyframeData: DictionaryInitializable where T: AnyInitializable {
|
|
convenience init(dictionary: [String: Any]) throws {
|
|
let startValue = try? dictionary[CodingKeys.startValue.rawValue].flatMap(T.init)
|
|
let endValue = try? dictionary[CodingKeys.endValue.rawValue].flatMap(T.init)
|
|
let time: AnimationFrameTime? = try? dictionary.value(for: CodingKeys.time)
|
|
let hold: Int? = try? dictionary.value(for: CodingKeys.hold)
|
|
let inTangent: Vector2D? = try? dictionary.value(for: CodingKeys.inTangent)
|
|
let outTangent: Vector2D? = try? dictionary.value(for: CodingKeys.outTangent)
|
|
let spatialInTangent: Vector3D? = try? dictionary.value(for: CodingKeys.spatialInTangent)
|
|
let spatialOutTangent: Vector3D? = try? dictionary.value(for: CodingKeys.spatialOutTangent)
|
|
|
|
self.init(
|
|
startValue: startValue,
|
|
endValue: endValue,
|
|
time: time,
|
|
hold: hold,
|
|
inTangent: inTangent,
|
|
outTangent: outTangent,
|
|
spatialInTangent: spatialInTangent,
|
|
spatialOutTangent: spatialOutTangent)
|
|
}
|
|
}
|