mirror of
https://github.com/exyte/Macaw.git
synced 2024-10-10 19:37:32 +03:00
Basic path animation implementation
This commit is contained in:
parent
8c32c64793
commit
41c61f2705
@ -4,155 +4,164 @@ import UIKit
|
||||
import Macaw
|
||||
|
||||
class ThirdPageCustomView: MacawView {
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
|
||||
func cloudExample() -> Group {
|
||||
func cloud1() -> Path {
|
||||
return Path(segments: [
|
||||
Move(x: 441.953, y: 142.352, absolute: true),
|
||||
Cubic(x1: -4.447, y1: -68.872, x2: -61.709, y2: -123.36, x: -131.705, y: -123.36, absolute: false),
|
||||
Cubic(x1: -59.481, y1: 0, x2: -109.766, y2: 39.346, x: -126.264, y: 93.429, absolute: false),
|
||||
Cubic(x1: -9.244, y1: -3.5, x2: -19.259, y2: -5.431, x: -29.729, y: -5.431, absolute: false),
|
||||
Cubic(x1: -42.84, y1: 0, x2: -78.164, y2: 32.08, x: -83.322, y: 73.523, absolute: false),
|
||||
Cubic(x1: -0.309, y1: -0.004, x2: -0.614, y2: -0.023, x: -0.924, y: -0.023, absolute: false),
|
||||
Cubic(x1: -36.863, y1: 0, x2: -66.747, y2: 29.883, x: -66.747, y: 66.747, absolute: false),
|
||||
SCubic(x2: 29.883, y2: 66.746, x: 66.747, y: 66.746, absolute: false),
|
||||
Cubic(x1: 4.386, y1: 0, x2: 8.669, y2: -0.436, x: 12.819, y: -1.243, absolute: false),
|
||||
Cubic(x1: 20.151, y1: 27.069, x2: 52.394, y2: 44.604, x: 88.734, y: 44.604, absolute: false),
|
||||
Cubic(x1: 31.229, y1: 0, x2: 59.429, y2: -12.952, x: 79.533, y: -33.772, absolute: false),
|
||||
Cubic(x1: 15.071, y1: 15.091, x2: 35.901, y2: 24.428, x: 58.913, y: 24.428, absolute: false),
|
||||
Cubic(x1: 31.43, y1: 0, x2: 58.783, y2: -17.42, x: 72.955, y: -43.127, absolute: false),
|
||||
Cubic(x1: 11.676, y1: 5.824, x2: 24.844, y2: 9.106, x: 38.777, y: 9.106, absolute: false),
|
||||
Cubic(x1: 48.047, y1: 0, x2: 86.998, y2: -38.949, x: 86.998, y: -86.996, absolute: false),
|
||||
Cubic(x1: 508.738, y1: 185.895, x2: 480.252, y2: 151.465, x: 441.953, y: 142.352, absolute: true),
|
||||
Close()
|
||||
])
|
||||
}
|
||||
|
||||
func cloud2() -> Path {
|
||||
return Path(segments: [
|
||||
Move(x: 431.357, y: 266.878, absolute: true),
|
||||
Cubic(x1: 0.058, y1: -1.449, x2: 0.187, y2: -2.878, x: 0.187, y: -4.333, absolute: false),
|
||||
Cubic(x1: 0, y1: -74.304, x2: -60.587, y2: -134.545, x: -135.315, y: -134.545, absolute: false),
|
||||
Cubic(x1: -54.09, y1: 0, x2: -100.571, y2: 31.647, x: -122.229, y: 77.266, absolute: false),
|
||||
Cubic(x1: -11.06, y1: -7.422, x2: -24.343, y2: -11.812, x: -38.686, y: -11.812, absolute: false),
|
||||
Cubic(x1: -36.586, y1: 0, x2: -66.518, y2: 28.14, x: -69.214, y: 63.836, absolute: false),
|
||||
Cubic(x1: 27.625, y1: 270.685, x2: 0, y2: 306.991, x: 0, y: 349.819, absolute: true),
|
||||
Cubic(x1: 0, y1: 404.045, x2: 44.2, y2: 448, x: 98.743, y: 448, absolute: true),
|
||||
HLine(x: 321.828, absolute: false),
|
||||
Cubic(x1: 471.057, y1: 448, x2: 512, y2: 407.29, x: 512, y: 357.091, absolute: true),
|
||||
Cubic(x1: 512, y1: 310.514, x2: 476.757, y2: 272.184, x: 431.357, y: 266.878, absolute: true),
|
||||
Close()
|
||||
])
|
||||
}
|
||||
|
||||
func lightning() -> Path {
|
||||
return Path(segments: [
|
||||
Move(x: 0, y: 0),
|
||||
PLine(x: 23, y: 23, absolute: true),
|
||||
PLine(x: 11, y: 27, absolute: true),
|
||||
PLine(x: 55, y: 70, absolute: true),
|
||||
PLine(x: 31, y: 31, absolute: true),
|
||||
PLine(x: 42, y: 27, absolute: true),
|
||||
PLine(x: 20, y: 0, absolute: true),
|
||||
Close()
|
||||
])
|
||||
}
|
||||
|
||||
let cloud2Shape = Shape(
|
||||
form: cloud2(),
|
||||
pos: Transform.scale(1.5, sy: 1.5).move(0, my: -100),
|
||||
fill: Color(val: 0x60636e),
|
||||
stroke: Stroke(
|
||||
fill: Color(val: 0x7e8087),
|
||||
width: 2,
|
||||
cap: .round,
|
||||
join: .round
|
||||
)
|
||||
)
|
||||
|
||||
let lightningShape = Shape(
|
||||
form: lightning(),
|
||||
pos: Transform.move(375, my: 390).scale(3, sy: 3),
|
||||
fill: LinearGradient(
|
||||
userSpace: true,
|
||||
stops: [
|
||||
Stop(offset: 0, color: Color.rgb(250, g: 220, b: 0)),
|
||||
Stop(offset: 1, color: Color(val: 0xeb6405))
|
||||
],
|
||||
y2: 1
|
||||
)
|
||||
)
|
||||
|
||||
let cloud1Shape = Shape(
|
||||
form: cloud1(),
|
||||
pos: Transform.move(120, my: 120),
|
||||
fill: LinearGradient(
|
||||
userSpace: false,
|
||||
stops: [
|
||||
Stop(offset: 0, color: Color(val: 0x2f3036)),
|
||||
Stop(offset: 1, color: Color.rgba(47, g: 48, b: 54, a: 0.1))
|
||||
],
|
||||
y2: 1
|
||||
)
|
||||
)
|
||||
|
||||
let cloud1Shape2 = Shape(
|
||||
form: cloud1(),
|
||||
pos: Transform.move(120, my: 100),
|
||||
fill: Color(val: 0x7b808c),
|
||||
stroke: Stroke(
|
||||
fill: Color(val: 0xaaacb3),
|
||||
width: 1,
|
||||
cap: .round,
|
||||
join: .round
|
||||
)
|
||||
)
|
||||
|
||||
return Group(
|
||||
contents: [cloud2Shape, lightningShape, cloud1Shape, cloud1Shape2],
|
||||
pos: Transform.move(220, my: 320).scale(0.15, sy: 0.15)
|
||||
)
|
||||
}
|
||||
|
||||
let cloud1 = cloudExample()
|
||||
let cloud2 = cloudExample()
|
||||
let cloud3 = cloudExample()
|
||||
|
||||
let group = Group(
|
||||
contents: [
|
||||
cloud1,
|
||||
cloud2,
|
||||
cloud3
|
||||
],
|
||||
pos: Transform().move(-80, my: -100)
|
||||
)
|
||||
|
||||
super.init(node: group, coder: aDecoder)
|
||||
|
||||
let cloud1ShapeAnimation = Animation(observableValue: cloud1.posProperty,
|
||||
finalValue:Transform.move(120, my: 120).scale(0.3, sy: 0.3),
|
||||
animationDuration: 1.5)
|
||||
|
||||
let cloud2ShapeAnimation = Animation(observableValue: cloud2.posProperty,
|
||||
finalValue:Transform.move(100, my: 320).scale(0.075, sy: 0.075),
|
||||
animationDuration: 1.5)
|
||||
|
||||
let cloud3ShapeAnimation = Animation(observableValue: cloud3.posProperty,
|
||||
finalValue:Transform.move(220, my: 420).scale(0.15, sy: 0.15),
|
||||
animationDuration: 1.5)
|
||||
let animation = [
|
||||
cloud1ShapeAnimation,
|
||||
cloud2ShapeAnimation.easeIn(),
|
||||
cloud3ShapeAnimation.easeOut()
|
||||
].animationSequence().looped().infiniteLoop()
|
||||
super.addAnimation(animation)
|
||||
|
||||
}
|
||||
|
||||
required init?(node: Node, coder aDecoder: NSCoder) {
|
||||
super.init(node: node, coder: aDecoder)
|
||||
}
|
||||
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
|
||||
func cloudExample() -> Group {
|
||||
func cloud1() -> Path {
|
||||
return Path(segments: [
|
||||
Move(x: 441.953, y: 142.352, absolute: true),
|
||||
Cubic(x1: -4.447, y1: -68.872, x2: -61.709, y2: -123.36, x: -131.705, y: -123.36, absolute: false),
|
||||
Cubic(x1: -59.481, y1: 0, x2: -109.766, y2: 39.346, x: -126.264, y: 93.429, absolute: false),
|
||||
Cubic(x1: -9.244, y1: -3.5, x2: -19.259, y2: -5.431, x: -29.729, y: -5.431, absolute: false),
|
||||
Cubic(x1: -42.84, y1: 0, x2: -78.164, y2: 32.08, x: -83.322, y: 73.523, absolute: false),
|
||||
Cubic(x1: -0.309, y1: -0.004, x2: -0.614, y2: -0.023, x: -0.924, y: -0.023, absolute: false),
|
||||
Cubic(x1: -36.863, y1: 0, x2: -66.747, y2: 29.883, x: -66.747, y: 66.747, absolute: false),
|
||||
SCubic(x2: 29.883, y2: 66.746, x: 66.747, y: 66.746, absolute: false),
|
||||
Cubic(x1: 4.386, y1: 0, x2: 8.669, y2: -0.436, x: 12.819, y: -1.243, absolute: false),
|
||||
Cubic(x1: 20.151, y1: 27.069, x2: 52.394, y2: 44.604, x: 88.734, y: 44.604, absolute: false),
|
||||
Cubic(x1: 31.229, y1: 0, x2: 59.429, y2: -12.952, x: 79.533, y: -33.772, absolute: false),
|
||||
Cubic(x1: 15.071, y1: 15.091, x2: 35.901, y2: 24.428, x: 58.913, y: 24.428, absolute: false),
|
||||
Cubic(x1: 31.43, y1: 0, x2: 58.783, y2: -17.42, x: 72.955, y: -43.127, absolute: false),
|
||||
Cubic(x1: 11.676, y1: 5.824, x2: 24.844, y2: 9.106, x: 38.777, y: 9.106, absolute: false),
|
||||
Cubic(x1: 48.047, y1: 0, x2: 86.998, y2: -38.949, x: 86.998, y: -86.996, absolute: false),
|
||||
Cubic(x1: 508.738, y1: 185.895, x2: 480.252, y2: 151.465, x: 441.953, y: 142.352, absolute: true),
|
||||
Close()
|
||||
])
|
||||
}
|
||||
|
||||
func cloud2() -> Path {
|
||||
return Path(segments: [
|
||||
Move(x: 431.357, y: 266.878, absolute: true),
|
||||
Cubic(x1: 0.058, y1: -1.449, x2: 0.187, y2: -2.878, x: 0.187, y: -4.333, absolute: false),
|
||||
Cubic(x1: 0, y1: -74.304, x2: -60.587, y2: -134.545, x: -135.315, y: -134.545, absolute: false),
|
||||
Cubic(x1: -54.09, y1: 0, x2: -100.571, y2: 31.647, x: -122.229, y: 77.266, absolute: false),
|
||||
Cubic(x1: -11.06, y1: -7.422, x2: -24.343, y2: -11.812, x: -38.686, y: -11.812, absolute: false),
|
||||
Cubic(x1: -36.586, y1: 0, x2: -66.518, y2: 28.14, x: -69.214, y: 63.836, absolute: false),
|
||||
Cubic(x1: 27.625, y1: 270.685, x2: 0, y2: 306.991, x: 0, y: 349.819, absolute: true),
|
||||
Cubic(x1: 0, y1: 404.045, x2: 44.2, y2: 448, x: 98.743, y: 448, absolute: true),
|
||||
HLine(x: 321.828, absolute: false),
|
||||
Cubic(x1: 471.057, y1: 448, x2: 512, y2: 407.29, x: 512, y: 357.091, absolute: true),
|
||||
Cubic(x1: 512, y1: 310.514, x2: 476.757, y2: 272.184, x: 431.357, y: 266.878, absolute: true),
|
||||
Close()
|
||||
])
|
||||
}
|
||||
|
||||
func lightning() -> Path {
|
||||
return Path(segments: [
|
||||
Move(x: 0, y: 0),
|
||||
PLine(x: 23, y: 23, absolute: true),
|
||||
PLine(x: 11, y: 27, absolute: true),
|
||||
PLine(x: 55, y: 70, absolute: true),
|
||||
PLine(x: 31, y: 31, absolute: true),
|
||||
PLine(x: 42, y: 27, absolute: true),
|
||||
PLine(x: 20, y: 0, absolute: true),
|
||||
Close()
|
||||
])
|
||||
}
|
||||
|
||||
let cloud2Shape = Shape(
|
||||
form: cloud2(),
|
||||
pos: Transform.scale(1.5, sy: 1.5).move(0, my: -100),
|
||||
fill: Color(val: 0x60636e),
|
||||
stroke: Stroke(
|
||||
fill: Color(val: 0x7e8087),
|
||||
width: 2,
|
||||
cap: .round,
|
||||
join: .round
|
||||
)
|
||||
)
|
||||
|
||||
let lightningShape = Shape(
|
||||
form: lightning(),
|
||||
pos: Transform.move(375, my: 390).scale(3, sy: 3),
|
||||
fill: LinearGradient(
|
||||
userSpace: true,
|
||||
stops: [
|
||||
Stop(offset: 0, color: Color.rgb(250, g: 220, b: 0)),
|
||||
Stop(offset: 1, color: Color(val: 0xeb6405))
|
||||
],
|
||||
y2: 1
|
||||
)
|
||||
)
|
||||
|
||||
let cloud1Shape = Shape(
|
||||
form: cloud1(),
|
||||
pos: Transform.move(120, my: 120),
|
||||
fill: LinearGradient(
|
||||
userSpace: false,
|
||||
stops: [
|
||||
Stop(offset: 0, color: Color(val: 0x2f3036)),
|
||||
Stop(offset: 1, color: Color.rgba(47, g: 48, b: 54, a: 0.1))
|
||||
],
|
||||
y2: 1
|
||||
)
|
||||
)
|
||||
|
||||
let cloud1Shape2 = Shape(
|
||||
form: cloud1(),
|
||||
pos: Transform.move(120, my: 100),
|
||||
fill: Color(val: 0x7b808c),
|
||||
stroke: Stroke(
|
||||
fill: Color(val: 0xaaacb3),
|
||||
width: 1,
|
||||
cap: .round,
|
||||
join: .round
|
||||
)
|
||||
)
|
||||
|
||||
return Group(
|
||||
contents: [cloud2Shape, lightningShape, cloud1Shape, cloud1Shape2],
|
||||
pos: Transform.move(220, my: 320).scale(0.15, sy: 0.15)
|
||||
)
|
||||
}
|
||||
|
||||
let cloud1 = cloudExample()
|
||||
let cloud2 = cloudExample()
|
||||
let cloud3 = cloudExample()
|
||||
|
||||
let group = Group(
|
||||
contents: [
|
||||
cloud1,
|
||||
cloud2,
|
||||
cloud3
|
||||
],
|
||||
pos: Transform().move(-80, my: -100)
|
||||
)
|
||||
|
||||
super.init(node: group, coder: aDecoder)
|
||||
|
||||
let cloud1ShapeAnimation = Animation(observableValue: cloud1.posProperty,
|
||||
finalValue: Transform.move(120, my: 120).scale(0.3, sy: 0.3),
|
||||
animationDuration: 1.5)
|
||||
|
||||
let cloud2ShapeAnimation = Animation(observableValue: cloud2.posProperty,
|
||||
finalValue: Transform.move(100, my: 320).scale(0.075, sy: 0.075),
|
||||
animationDuration: 1.5)
|
||||
|
||||
// let cloud3ShapeAnimation = Animation(observableValue: cloud3.posProperty,
|
||||
// finalValue: Transform.move(220, my: 420).scale(0.15, sy: 0.15),
|
||||
// animationDuration: 1.5)
|
||||
|
||||
let path = [
|
||||
AnimationPathFrameMake(Transform.move(220, my: 320 + 50 * sin(0.0)).scale(0.15, sy: 0.15), position: 0.0),
|
||||
AnimationPathFrameMake(Transform.move(180, my: 320 + 50 * sin(M_PI * 0.5)).scale(0.15, sy: 0.15), position: 0.25),
|
||||
AnimationPathFrameMake(Transform.move(140, my: 320 + 50 * sin(M_PI)).scale(0.15, sy: 0.15), position: 0.5),
|
||||
AnimationPathFrameMake(Transform.move(100, my: 320 + 50 * sin(M_PI * 1.5)).scale(0.15, sy: 0.15), position: 0.75),
|
||||
AnimationPathFrameMake(Transform.move(60, my: 320 + 50 * sin(M_PI * 2.0)).scale(0.15, sy: 0.15), position: 1.0)
|
||||
]
|
||||
let cloud3ShapeAnimation = PathAnimation(observableValue: cloud3.posProperty,
|
||||
path: path,
|
||||
animationDuration: 3.0)
|
||||
let animation = [
|
||||
cloud1ShapeAnimation,
|
||||
cloud2ShapeAnimation.easeIn(),
|
||||
cloud3ShapeAnimation.easeOut()
|
||||
].animationSequence().looped().infiniteLoop()
|
||||
super.addAnimation(animation)
|
||||
}
|
||||
|
||||
required init?(node: Node, coder aDecoder: NSCoder) {
|
||||
super.init(node: node, coder: aDecoder)
|
||||
}
|
||||
}
|
||||
|
@ -21,6 +21,7 @@
|
||||
574BDD9A1CAAA5540031D313 /* DoubleInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574BDD991CAAA5540031D313 /* DoubleInterpolation.swift */; };
|
||||
574BDD9C1CAAA5D60031D313 /* TransformInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574BDD9B1CAAA5D60031D313 /* TransformInterpolation.swift */; };
|
||||
5754E63F1CB3B70D00657DA3 /* EasingAnimations.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5754E63E1CB3B70D00657DA3 /* EasingAnimations.swift */; };
|
||||
575C9AC81CB4D35200CB572C /* PathAnimation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 575C9AC71CB4D35200CB572C /* PathAnimation.swift */; };
|
||||
585C04481C27CFB100335FF2 /* MacawView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 585C04471C27CFB100335FF2 /* MacawView.swift */; };
|
||||
B0086C561C789758008A4F69 /* GroupRenderer.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0086C551C789758008A4F69 /* GroupRenderer.swift */; };
|
||||
B0097E081C706CAB00350E43 /* ObservableValue.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0097E071C706CAB00350E43 /* ObservableValue.swift */; };
|
||||
@ -96,6 +97,7 @@
|
||||
574BDD991CAAA5540031D313 /* DoubleInterpolation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoubleInterpolation.swift; sourceTree = "<group>"; };
|
||||
574BDD9B1CAAA5D60031D313 /* TransformInterpolation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TransformInterpolation.swift; sourceTree = "<group>"; };
|
||||
5754E63E1CB3B70D00657DA3 /* EasingAnimations.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EasingAnimations.swift; sourceTree = "<group>"; };
|
||||
575C9AC71CB4D35200CB572C /* PathAnimation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PathAnimation.swift; sourceTree = "<group>"; };
|
||||
585C04471C27CFB100335FF2 /* MacawView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MacawView.swift; sourceTree = "<group>"; };
|
||||
B0086C551C789758008A4F69 /* GroupRenderer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GroupRenderer.swift; sourceTree = "<group>"; };
|
||||
B0097E071C706CAB00350E43 /* ObservableValue.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ObservableValue.swift; sourceTree = "<group>"; };
|
||||
@ -177,6 +179,7 @@
|
||||
573AA6A31CAE402C00F30607 /* RevertedAnimation.swift */,
|
||||
573AA6A51CAE41D400F30607 /* LoopedAnimation.swift */,
|
||||
5754E63E1CB3B70D00657DA3 /* EasingAnimations.swift */,
|
||||
575C9AC71CB4D35200CB572C /* PathAnimation.swift */,
|
||||
);
|
||||
path = types;
|
||||
sourceTree = "<group>";
|
||||
@ -499,6 +502,7 @@
|
||||
B03275F11C78772F000BDD33 /* Stop.swift in Sources */,
|
||||
573AA6A01CAE346900F30607 /* AnimationSequence.swift in Sources */,
|
||||
B03276171C788162000BDD33 /* ShapeRenderer.swift in Sources */,
|
||||
575C9AC81CB4D35200CB572C /* PathAnimation.swift in Sources */,
|
||||
B03275EA1C78772F000BDD33 /* Fill.swift in Sources */,
|
||||
B03275F51C78772F000BDD33 /* Close.swift in Sources */,
|
||||
B03275F01C78772F000BDD33 /* LineJoin.swift in Sources */,
|
||||
|
76
Source/animation/types/PathAnimation.swift
Normal file
76
Source/animation/types/PathAnimation.swift
Normal file
@ -0,0 +1,76 @@
|
||||
import Foundation
|
||||
|
||||
public struct AnimationPathFrame<T: Interpolable> {
|
||||
|
||||
let value: T
|
||||
let position: Double
|
||||
}
|
||||
|
||||
public func AnimationPathFrameMake<T>(value: T, position: Double) -> AnimationPathFrame<T> {
|
||||
return AnimationPathFrame(value: value, position: position)
|
||||
}
|
||||
|
||||
public struct AnimationPathSegment<T: Interpolable> {
|
||||
let start: AnimationPathFrame<T>
|
||||
let end: AnimationPathFrame<T>
|
||||
|
||||
func contains(position: Double) -> Bool {
|
||||
return position > start.position && position <= end.position
|
||||
}
|
||||
}
|
||||
|
||||
public class PathAnimation<T: Interpolable>: Animatable {
|
||||
|
||||
let value: ObservableValue<T>
|
||||
let pathSegments: [AnimationPathSegment<T>]
|
||||
let duration: Double
|
||||
|
||||
var cachedSegment: AnimationPathSegment<T>?
|
||||
|
||||
public required init(observableValue: ObservableValue<T>, path: [AnimationPathFrame<T>], animationDuration: Double) {
|
||||
value = observableValue
|
||||
duration = animationDuration
|
||||
|
||||
var prevFrame: AnimationPathFrame<T>?
|
||||
var segments = [AnimationPathSegment<T>]()
|
||||
for frame in path {
|
||||
if let prevFrame = prevFrame {
|
||||
let segment = AnimationPathSegment(start: prevFrame, end: frame)
|
||||
segments.append(segment)
|
||||
}
|
||||
|
||||
prevFrame = frame
|
||||
}
|
||||
|
||||
pathSegments = segments
|
||||
}
|
||||
|
||||
public override func animate(progress: Double) {
|
||||
|
||||
// Cache
|
||||
if let cachedSegment = cachedSegment {
|
||||
if cachedSegment.contains(progress) {
|
||||
value.set(iterpolate(cachedSegment, position: progress))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Changing segment
|
||||
for segment in pathSegments {
|
||||
if segment.contains(progress) {
|
||||
cachedSegment = segment
|
||||
value.set(iterpolate(segment, position: progress))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override func getDuration() -> Double {
|
||||
return duration
|
||||
}
|
||||
|
||||
private func iterpolate(segment: AnimationPathSegment<T>, position: Double) -> T {
|
||||
let relativePosition = (position - segment.start.position) / (segment.end.position - segment.start.position)
|
||||
return segment.start.value.interpolate(segment.end.value, progress: relativePosition)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user