1
1
mirror of https://github.com/exyte/Macaw.git synced 2024-10-10 19:37:32 +03:00

Animation refactoring

This commit is contained in:
Victor Sukochev 2016-04-05 15:03:00 +06:00
parent 23594868c6
commit d2c3f0e65c
16 changed files with 70 additions and 90 deletions

View File

@ -131,19 +131,23 @@ class ThirdPageCustomView: MacawView {
super.init(node: group, coder: aDecoder)
let cloud1ShapeAnimation = Animation(observableProperty: cloud1.posProperty,
let cloud1ShapeAnimation = Animation(observableValue: cloud1.posProperty,
finalValue:Transform.move(120, my: 120).scale(0.3, sy: 0.3),
animationDuration: 1.5)
let cloud2ShapeAnimation = Animation(observableProperty: cloud2.posProperty,
let cloud2ShapeAnimation = Animation(observableValue: cloud2.posProperty,
finalValue:Transform.move(100, my: 320).scale(0.075, sy: 0.075),
animationDuration: 1.5)
let cloud3ShapeAnimation = Animation(observableProperty: cloud3.posProperty,
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, cloud3ShapeAnimation].sequence().looped().infiniteLoop()
let animation = [
cloud1ShapeAnimation,
cloud2ShapeAnimation,
cloud3ShapeAnimation
].sequence().looped().infiniteLoop()
super.addAnimation(animation)
// super.addAnimation(cloud1ShapeAnimation)

View File

@ -15,7 +15,7 @@
574223901CA5448C001EE463 /* Animation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5742238F1CA5448C001EE463 /* Animation.swift */; };
574223921CA55360001EE463 /* AnimationSubscription.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574223911CA55360001EE463 /* AnimationSubscription.swift */; };
574BDD921CAA7FC50031D313 /* IntInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574BDD911CAA7FC50031D313 /* IntInterpolation.swift */; };
574BDD941CAA80070031D313 /* TypeInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574BDD931CAA80070031D313 /* TypeInterpolation.swift */; };
574BDD941CAA80070031D313 /* Interpolable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574BDD931CAA80070031D313 /* Interpolable.swift */; };
574BDD961CAA861B0031D313 /* CGFloatInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574BDD951CAA861B0031D313 /* CGFloatInterpolation.swift */; };
574BDD981CAA86CC0031D313 /* CGPointInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574BDD971CAA86CC0031D313 /* CGPointInterpolation.swift */; };
574BDD9A1CAAA5540031D313 /* DoubleInterpolation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 574BDD991CAAA5540031D313 /* DoubleInterpolation.swift */; };
@ -89,7 +89,7 @@
5742238F1CA5448C001EE463 /* Animation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Animation.swift; sourceTree = "<group>"; };
574223911CA55360001EE463 /* AnimationSubscription.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnimationSubscription.swift; sourceTree = "<group>"; };
574BDD911CAA7FC50031D313 /* IntInterpolation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = IntInterpolation.swift; sourceTree = "<group>"; };
574BDD931CAA80070031D313 /* TypeInterpolation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TypeInterpolation.swift; sourceTree = "<group>"; };
574BDD931CAA80070031D313 /* Interpolable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Interpolable.swift; sourceTree = "<group>"; };
574BDD951CAA861B0031D313 /* CGFloatInterpolation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGFloatInterpolation.swift; sourceTree = "<group>"; };
574BDD971CAA86CC0031D313 /* CGPointInterpolation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CGPointInterpolation.swift; sourceTree = "<group>"; };
574BDD991CAAA5540031D313 /* DoubleInterpolation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DoubleInterpolation.swift; sourceTree = "<group>"; };
@ -186,7 +186,7 @@
5742238D1CA5414E001EE463 /* AnimationLoop.swift */,
5742238F1CA5448C001EE463 /* Animation.swift */,
574223911CA55360001EE463 /* AnimationSubscription.swift */,
574BDD931CAA80070031D313 /* TypeInterpolation.swift */,
574BDD931CAA80070031D313 /* Interpolable.swift */,
);
path = animation;
sourceTree = "<group>";
@ -456,7 +456,7 @@
B03275FB1C78772F000BDD33 /* Line.swift in Sources */,
B032760A1C78772F000BDD33 /* Transform.swift in Sources */,
B032760C1C78772F000BDD33 /* Cursor.swift in Sources */,
574BDD941CAA80070031D313 /* TypeInterpolation.swift in Sources */,
574BDD941CAA80070031D313 /* Interpolable.swift in Sources */,
B03275EF1C78772F000BDD33 /* LineCap.swift in Sources */,
573AA6A41CAE402C00F30607 /* RevertedAnimation.swift in Sources */,
573AA6A61CAE41D400F30607 /* LoopedAnimation.swift in Sources */,

View File

@ -1,41 +1,34 @@
import Foundation
public protocol CommonAnimation {
public protocol Animatable {
func animate(progress: Double)
func getDuration() -> Double
}
public class Animation<T: InterpolatingType>: CommonAnimation {
public class Animation<T: Interpolable>: Animatable {
var property: ObservableValue<T>?
let value: ObservableValue<T>
var start: T?
var final: T?
var duration: Double = 0
let start: T
let final: T
let duration: Double
public required init(observableProperty: ObservableValue<T>?, startValue: T?, finalValue: T?, animationDuration: Double) {
property = observableProperty
public required init(observableValue: ObservableValue<T>, startValue: T, finalValue: T, animationDuration: Double) {
value = observableValue
start = startValue
final = finalValue
duration = animationDuration
}
public convenience init(observableProperty: ObservableValue<T>?, finalValue: T, animationDuration: Double) {
self.init(observableProperty: observableProperty, startValue: observableProperty?.get(), finalValue: finalValue, animationDuration: animationDuration )
public convenience init(observableValue: ObservableValue<T>, finalValue: T, animationDuration: Double) {
self.init(observableValue: observableValue, startValue: observableValue.get(), finalValue: finalValue, animationDuration: animationDuration )
}
public func animate(progress: Double) {
guard let start = start else {
return
}
guard let final = final else {
return
}
property?.set(start.interpolate(final, progress: progress))
value.set(start.interpolate(final, progress: progress))
}
public func getDuration() -> Double {

View File

@ -20,10 +20,6 @@ class AnimationLoop {
animationSubscriptions.forEach { subscription in
guard let animation = subscription.anim else {
return
}
if subscription.startTime == .None {
subscription.startTime = displayLink.timestamp
}
@ -33,7 +29,7 @@ class AnimationLoop {
}
let timePosition = displayLink.timestamp - startTime
let position = timePosition / animation.getDuration()
let position = timePosition / subscription.anim.getDuration()
if position > 1.0 {
toRemove.append(subscription)

View File

@ -2,15 +2,15 @@ import Foundation
class AnimationSubscription {
var anim: CommonAnimation?
let anim: Animatable
var startTime: CFTimeInterval?
init( animation: CommonAnimation ) {
init( animation: Animatable ) {
anim = animation
}
func moveToTimeFrame(position: Double, advance: Double) {
anim?.animate(position)
anim.animate(position)
}
}

View File

@ -1,6 +1,6 @@
import Foundation
public protocol InterpolatingType {
public protocol Interpolable {
func interpolate(endValue: Self, progress: Double) -> Self
}

View File

@ -1,7 +1,7 @@
import UIKit
extension CGFloat: InterpolatingType {
extension CGFloat: Interpolable {
public func interpolate(endValue: CGFloat, progress: Double) -> CGFloat {
return self * CGFloat(1.0 - progress) + endValue * CGFloat(progress)
return self + (endValue - self) * CGFloat(progress)
}
}

View File

@ -1,6 +1,6 @@
import UIKit
extension CGPoint: InterpolatingType {
extension CGPoint: Interpolable {
public func interpolate(endValue: CGPoint, progress: Double) -> CGPoint {
return CGPoint(x: self.x.interpolate(endValue.x, progress: progress),
y: self.y.interpolate(endValue.y, progress: progress))

View File

@ -1,7 +1,7 @@
import Foundation
extension Double: InterpolatingType {
extension Double: Interpolable {
public func interpolate(endValue: Double, progress: Double) -> Double {
return self * (1.0 - progress) + endValue * progress
return self + (endValue - self) * progress
}
}

View File

@ -1,8 +1,7 @@
import Foundation
extension Int: InterpolatingType {
extension Int: Interpolable {
public func interpolate(endValue: Int, progress: Double) -> Int {
return Int(Double(self) * (1.0 - progress) + Double(endValue) * progress)
return Int(Double(self) + Double(endValue - self) * progress)
}
}

View File

@ -1,6 +1,6 @@
import Foundation
extension Transform: InterpolatingType {
extension Transform: Interpolable {
public func interpolate(endValue: Transform, progress: Double) -> Transform {
return Transform(m11: self.m11.interpolate(endValue.m11, progress: progress),
m12: self.m12.interpolate(endValue.m12, progress: progress),

View File

@ -1,7 +1,7 @@
import Foundation
public extension SequenceType where Generator.Element: CommonAnimation{
public func sequence() -> CommonAnimation {
public extension SequenceType where Generator.Element: Animatable{
public func sequence() -> Animatable {
let sequence = AnimationSequence(animations:[])
self.forEach { animation in
sequence.addAnimation(animation)
@ -11,20 +11,20 @@ public extension SequenceType where Generator.Element: CommonAnimation{
}
}
public class AnimationSequence: CommonAnimation {
public class AnimationSequence: Animatable {
var sequence: [CommonAnimation] = []
var sequence: [Animatable] = []
public required init(animations: [CommonAnimation]) {
public required init(animations: [Animatable]) {
sequence.appendContentsOf(animations)
}
public convenience init(animation: CommonAnimation) {
public convenience init(animation: Animatable) {
self.init(animations: [animation])
}
public func addAnimation(animation: CommonAnimation) {
public func addAnimation(animation: Animatable) {
sequence.append(animation)
}

View File

@ -1,27 +1,23 @@
import Foundation
public extension CommonAnimation {
public func looped() -> CommonAnimation {
public extension Animatable {
public func looped() -> Animatable {
return LoopedAnimation(animation: self)
}
}
public class LoopedAnimation: CommonAnimation {
var loopedlAnimation: CommonAnimation?
public class LoopedAnimation: Animatable {
let loopedlAnimation: Animatable
public required init(animation: CommonAnimation) {
public required init(animation: Animatable) {
loopedlAnimation = AnimationSequence(animations: [animation, RevertedAnimation(animation: animation)])
}
public func animate(progress: Double) {
loopedlAnimation?.animate(progress)
loopedlAnimation.animate(progress)
}
public func getDuration() -> Double {
guard let duration = loopedlAnimation?.getDuration() else {
return 0.0
}
return duration
return loopedlAnimation.getDuration()
}
}

View File

@ -6,22 +6,22 @@ public enum RepetitiveAnimationType {
case Infinite
}
public extension CommonAnimation {
public func infiniteLoop() -> CommonAnimation {
public extension Animatable {
public func infiniteLoop() -> Animatable {
return RepetitiveAnimation(animation: self)
}
public func loop(count: Int) -> CommonAnimation {
public func loop(count: Int) -> Animatable {
return RepetitiveAnimation(animation: self, count: count)
}
}
public class RepetitiveAnimation: CommonAnimation {
public class RepetitiveAnimation: Animatable {
var loopAnimation: CommonAnimation?
var loopsCount = 0
let loopAnimation: Animatable
var loopsCount: Int
public required init(animation: CommonAnimation, type: RepetitiveAnimationType, count: Int) {
public required init(animation: Animatable, type: RepetitiveAnimationType, count: Int) {
loopAnimation = animation
loopsCount = count
@ -30,11 +30,11 @@ public class RepetitiveAnimation: CommonAnimation {
}
}
public convenience init(animation: CommonAnimation, count: Int) {
public convenience init(animation: Animatable, count: Int) {
self.init(animation: animation, type: .Finite, count: count)
}
public convenience init(animation: CommonAnimation) {
public convenience init(animation: Animatable) {
self.init(animation: animation, type: .Infinite, count: 0)
}
@ -42,14 +42,10 @@ public class RepetitiveAnimation: CommonAnimation {
let progressInterval = 1.0 / Double(loopsCount)
let relativeProgress = (progress % progressInterval) * Double(loopsCount)
loopAnimation?.animate(relativeProgress)
loopAnimation.animate(relativeProgress)
}
public func getDuration() -> Double {
guard let duration = loopAnimation?.getDuration() else {
return 0
}
return Double(loopsCount) * duration
return Double(loopsCount) * loopAnimation.getDuration()
}
}

View File

@ -1,28 +1,24 @@
import Foundation
public extension CommonAnimation {
public func revert() -> CommonAnimation {
public extension Animatable {
public func revert() -> Animatable {
return RevertedAnimation(animation: self)
}
}
public class RevertedAnimation: CommonAnimation {
var originalAnimation: CommonAnimation?
public class RevertedAnimation: Animatable {
let originalAnimation: Animatable
public required init(animation: CommonAnimation) {
public required init(animation: Animatable) {
originalAnimation = animation
}
public func animate(progress: Double) {
originalAnimation?.animate(1.0 - progress)
originalAnimation.animate(1.0 - progress)
}
public func getDuration() -> Double {
guard let duration = originalAnimation?.getDuration() else {
return 0.0
}
return duration
return originalAnimation.getDuration()
}
}

View File

@ -30,7 +30,7 @@ public class MacawView: UIView {
renderer.render()
}
public func addAnimation(animation: CommonAnimation) {
public func addAnimation(animation: Animatable) {
let subscription = AnimationSubscription(animation: animation)
self.loop?.animationSubscriptions.append(subscription)
}