Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
Motion
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Dmitriy Stepanets
Motion
Commits
1bce1231
Unverified
Commit
1bce1231
authored
Jun 05, 2017
by
Daniel Dahan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
reworked MotionDefaultAnimator
parent
2caa4eb1
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
237 additions
and
120 deletions
+237
-120
Motion.xcodeproj/project.pbxproj
+4
-0
Sources/Animator/MotionAnimatorViewContext.swift
+8
-8
Sources/Animator/MotionCoreAnimationViewContext.swift
+2
-2
Sources/Animator/MotionDefaultAnimator.swift
+88
-79
Sources/Animator/MotionHasInsertOrder.swift
+32
-0
Sources/Debug Plugin/MotionDebugPlugin.swift
+1
-1
Sources/Extensions/Motion+UIView.swift
+23
-0
Sources/Motion.swift
+1
-1
Sources/MotionController.swift
+4
-6
Sources/MotionPlugin.swift
+2
-2
Sources/MotionTypes.swift
+72
-21
No files found.
Motion.xcodeproj/project.pbxproj
View file @
1bce1231
...
@@ -11,6 +11,7 @@
...
@@ -11,6 +11,7 @@
963150D21EE50DA6002B0D42
/* Motion+Obj-C.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
963150D11EE50DA6002B0D42
/* Motion+Obj-C.swift */
;
};
963150D21EE50DA6002B0D42
/* Motion+Obj-C.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
963150D11EE50DA6002B0D42
/* Motion+Obj-C.swift */
;
};
963150D61EE51C7A002B0D42
/* MotionAnimation.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
963150D41EE51C7A002B0D42
/* MotionAnimation.swift */
;
};
963150D61EE51C7A002B0D42
/* MotionAnimation.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
963150D41EE51C7A002B0D42
/* MotionAnimation.swift */
;
};
963150DA1EE51EB4002B0D42
/* MotionAnimationFillMode.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
963150D91EE51EB4002B0D42
/* MotionAnimationFillMode.swift */
;
};
963150DA1EE51EB4002B0D42
/* MotionAnimationFillMode.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
963150D91EE51EB4002B0D42
/* MotionAnimationFillMode.swift */
;
};
968989B91EE5B34B003B8F3D
/* MotionHasInsertOrder.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
968989B81EE5B34B003B8F3D
/* MotionHasInsertOrder.swift */
;
};
96AEB68D1EE4610F009A3BE0
/* MotionAnimatorViewContext.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96AEB6651EE4610F009A3BE0
/* MotionAnimatorViewContext.swift */
;
};
96AEB68D1EE4610F009A3BE0
/* MotionAnimatorViewContext.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96AEB6651EE4610F009A3BE0
/* MotionAnimatorViewContext.swift */
;
};
96AEB68E1EE4610F009A3BE0
/* MotionCoreAnimationViewContext.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96AEB6661EE4610F009A3BE0
/* MotionCoreAnimationViewContext.swift */
;
};
96AEB68E1EE4610F009A3BE0
/* MotionCoreAnimationViewContext.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96AEB6661EE4610F009A3BE0
/* MotionCoreAnimationViewContext.swift */
;
};
96AEB68F1EE4610F009A3BE0
/* MotionDefaultAnimator.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96AEB6671EE4610F009A3BE0
/* MotionDefaultAnimator.swift */
;
};
96AEB68F1EE4610F009A3BE0
/* MotionDefaultAnimator.swift in Sources */
=
{
isa
=
PBXBuildFile
;
fileRef
=
96AEB6671EE4610F009A3BE0
/* MotionDefaultAnimator.swift */
;
};
...
@@ -52,6 +53,7 @@
...
@@ -52,6 +53,7 @@
963150D11EE50DA6002B0D42
/* Motion+Obj-C.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"Motion+Obj-C.swift"
;
sourceTree
=
"<group>"
;
};
963150D11EE50DA6002B0D42
/* Motion+Obj-C.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
"Motion+Obj-C.swift"
;
sourceTree
=
"<group>"
;
};
963150D41EE51C7A002B0D42
/* MotionAnimation.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionAnimation.swift
;
sourceTree
=
"<group>"
;
};
963150D41EE51C7A002B0D42
/* MotionAnimation.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionAnimation.swift
;
sourceTree
=
"<group>"
;
};
963150D91EE51EB4002B0D42
/* MotionAnimationFillMode.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionAnimationFillMode.swift
;
sourceTree
=
"<group>"
;
};
963150D91EE51EB4002B0D42
/* MotionAnimationFillMode.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionAnimationFillMode.swift
;
sourceTree
=
"<group>"
;
};
968989B81EE5B34B003B8F3D
/* MotionHasInsertOrder.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionHasInsertOrder.swift
;
sourceTree
=
"<group>"
;
};
96AEB6651EE4610F009A3BE0
/* MotionAnimatorViewContext.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionAnimatorViewContext.swift
;
sourceTree
=
"<group>"
;
};
96AEB6651EE4610F009A3BE0
/* MotionAnimatorViewContext.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionAnimatorViewContext.swift
;
sourceTree
=
"<group>"
;
};
96AEB6661EE4610F009A3BE0
/* MotionCoreAnimationViewContext.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionCoreAnimationViewContext.swift
;
sourceTree
=
"<group>"
;
};
96AEB6661EE4610F009A3BE0
/* MotionCoreAnimationViewContext.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionCoreAnimationViewContext.swift
;
sourceTree
=
"<group>"
;
};
96AEB6671EE4610F009A3BE0
/* MotionDefaultAnimator.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionDefaultAnimator.swift
;
sourceTree
=
"<group>"
;
};
96AEB6671EE4610F009A3BE0
/* MotionDefaultAnimator.swift */
=
{
isa
=
PBXFileReference
;
fileEncoding
=
4
;
lastKnownFileType
=
sourcecode.swift
;
path
=
MotionDefaultAnimator.swift
;
sourceTree
=
"<group>"
;
};
...
@@ -111,6 +113,7 @@
...
@@ -111,6 +113,7 @@
96AEB6661EE4610F009A3BE0
/* MotionCoreAnimationViewContext.swift */
,
96AEB6661EE4610F009A3BE0
/* MotionCoreAnimationViewContext.swift */
,
96AEB6671EE4610F009A3BE0
/* MotionDefaultAnimator.swift */
,
96AEB6671EE4610F009A3BE0
/* MotionDefaultAnimator.swift */
,
96AEB6681EE4610F009A3BE0
/* MotionViewPropertyViewContext.swift */
,
96AEB6681EE4610F009A3BE0
/* MotionViewPropertyViewContext.swift */
,
968989B81EE5B34B003B8F3D
/* MotionHasInsertOrder.swift */
,
);
);
path
=
Animator
;
path
=
Animator
;
sourceTree
=
"<group>"
;
sourceTree
=
"<group>"
;
...
@@ -296,6 +299,7 @@
...
@@ -296,6 +299,7 @@
96AEB69D1EE4610F009A3BE0
/* Motion.swift in Sources */
,
96AEB69D1EE4610F009A3BE0
/* Motion.swift in Sources */
,
963150D61EE51C7A002B0D42
/* MotionAnimation.swift in Sources */
,
963150D61EE51C7A002B0D42
/* MotionAnimation.swift in Sources */
,
96AEB6A21EE4610F009A3BE0
/* MotionTransition+MotionStringConvertible.swift in Sources */
,
96AEB6A21EE4610F009A3BE0
/* MotionTransition+MotionStringConvertible.swift in Sources */
,
968989B91EE5B34B003B8F3D
/* MotionHasInsertOrder.swift in Sources */
,
96AEB6A51EE4610F009A3BE0
/* MotionTargetState.swift in Sources */
,
96AEB6A51EE4610F009A3BE0
/* MotionTargetState.swift in Sources */
,
96AEB6961EE4610F009A3BE0
/* Motion+CAMediaTimingFunction.swift in Sources */
,
96AEB6961EE4610F009A3BE0
/* Motion+CAMediaTimingFunction.swift in Sources */
,
96AEB6941EE4610F009A3BE0
/* Motion+Array.swift in Sources */
,
96AEB6941EE4610F009A3BE0
/* Motion+Array.swift in Sources */
,
...
...
Sources/Animator/MotionAnimatorViewContext.swift
View file @
1bce1231
...
@@ -81,19 +81,13 @@ internal class MotionAnimatorViewContext {
...
@@ -81,19 +81,13 @@ internal class MotionAnimatorViewContext {
}
}
/**
/**
Applies the given state to the target state.
- Parameter state: A MotionTargetState.
*/
func
apply
(
state
:
MotionTargetState
)
{}
/**
Resumes the animation with a given elapsed time and
Resumes the animation with a given elapsed time and
optional reversed boolean.
optional reversed boolean.
- Parameter elapsedTime: A TimeInterval.
- Parameter
at
elapsedTime: A TimeInterval.
- Parameter isReversed: A boolean to reverse the animation
- Parameter isReversed: A boolean to reverse the animation
or not.
or not.
*/
*/
func
resume
(
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
{}
func
resume
(
at
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
{}
/**
/**
Moves the animation to the given elapsed time.
Moves the animation to the given elapsed time.
...
@@ -102,6 +96,12 @@ internal class MotionAnimatorViewContext {
...
@@ -102,6 +96,12 @@ internal class MotionAnimatorViewContext {
func
seek
(
to
elapsedTime
:
TimeInterval
)
{}
func
seek
(
to
elapsedTime
:
TimeInterval
)
{}
/**
/**
Applies the given state to the target state.
- Parameter state: A MotionTargetState.
*/
func
apply
(
state
:
MotionTargetState
)
{}
/**
Starts the animations with an appearing boolean flag.
Starts the animations with an appearing boolean flag.
- Parameter isAppearing: A boolean value whether the view
- Parameter isAppearing: A boolean value whether the view
is appearing or not.
is appearing or not.
...
...
Sources/Animator/MotionCoreAnimationViewContext.swift
View file @
1bce1231
...
@@ -80,7 +80,7 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
...
@@ -80,7 +80,7 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
}
}
}
}
override
func
resume
(
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
{
override
func
resume
(
at
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
{
for
(
key
,
(
fromValue
,
toValue
))
in
transitionStates
{
for
(
key
,
(
fromValue
,
toValue
))
in
transitionStates
{
transitionStates
[
key
]
=
(
currentValue
(
for
:
key
),
!
isReversed
?
toValue
:
fromValue
)
transitionStates
[
key
]
=
(
currentValue
(
for
:
key
),
!
isReversed
?
toValue
:
fromValue
)
}
}
...
@@ -318,7 +318,7 @@ extension MotionCoreAnimationViewContext {
...
@@ -318,7 +318,7 @@ extension MotionCoreAnimationViewContext {
}
}
/**
/**
Constructs a map of key paths to animation values.
Constructs a map of key paths to animation
state
values.
- Parameter targetState state: A MotionTargetState.
- Parameter targetState state: A MotionTargetState.
- Returns: A map of key paths to animation values.
- Returns: A map of key paths to animation values.
*/
*/
...
...
Sources/Animator/MotionDefaultAnimator.swift
View file @
1bce1231
...
@@ -28,93 +28,102 @@
...
@@ -28,93 +28,102 @@
import
UIKit
import
UIKit
internal
extension
UIView
{
internal
class
MotionDefaultAnimator
<
T
:
MotionAnimatorViewContext
>
:
MotionAnimator
,
MotionHasInsertOrder
{
func
optimizedDuration
(
fromPosition
:
CGPoint
,
toPosition
:
CGPoint
?,
size
:
CGSize
?,
transform
:
CATransform3D
?)
->
TimeInterval
{
/// A reference to a MotionContext.
let
fromPos
=
fromPosition
weak
public
var
context
:
MotionContext
!
let
toPos
=
toPosition
??
fromPos
let
fromSize
=
(
layer
.
presentation
()
??
layer
)
.
bounds
.
size
/// An index of views to their corresponding animator context.
let
toSize
=
size
??
fromSize
var
viewToContexts
=
[
UIView
:
T
]()
let
fromTransform
=
(
layer
.
presentation
()
??
layer
)
.
transform
let
toTransform
=
transform
??
fromTransform
var
insertToViewFirst
=
false
let
realFromPos
=
CGPoint
.
zero
.
transform
(
fromTransform
)
+
fromPos
let
realToPos
=
CGPoint
.
zero
.
transform
(
toTransform
)
+
toPos
let
realFromSize
=
fromSize
.
transform
(
fromTransform
)
let
realToSize
=
toSize
.
transform
(
toTransform
)
let
movePoints
=
(
realFromPos
.
distance
(
realToPos
)
+
realFromSize
.
point
.
distance
(
realToSize
.
point
))
// duration is 0.2 @ 0 to 0.375 @ 500
let
duration
=
0.208
+
Double
(
movePoints
.
clamp
(
0
,
500
))
/
3000
return
duration
}
}
}
protocol
HasInsertOrder
:
class
{
extension
MotionDefaultAnimator
{
var
insertToViewFirst
:
Bool
{
get
set
}
/**
Animates a given view.
- Parameter view: A UIView.
- Parameter isAppearing: A boolean that determines whether the
view is appearing.
*/
fileprivate
func
animate
(
view
:
UIView
,
isAppearing
:
Bool
)
{
let
s
=
context
.
snapshotView
(
for
:
view
)
let
v
=
T
(
animator
:
self
,
snapshot
:
s
,
targetState
:
context
[
view
]
!
)
viewToContexts
[
view
]
=
v
v
.
startAnimations
(
isAppearing
:
isAppearing
)
}
}
}
internal
class
MotionDefaultAnimator
<
ViewContext
:
MotionAnimatorViewContext
>
:
MotionAnimator
,
HasInsertOrder
{
weak
public
var
context
:
MotionContext
!
var
viewContexts
:
[
UIView
:
ViewContext
]
=
[:]
internal
var
insertToViewFirst
=
false
public
func
seekTo
(
elapsedTime
:
TimeInterval
)
{
extension
MotionDefaultAnimator
{
for
viewContext
in
viewContexts
.
values
{
func
clean
()
{
viewContext
.
seek
(
to
:
elapsedTime
)
for
v
in
viewToContexts
.
values
{
v
.
clean
()
}
viewToContexts
.
removeAll
()
insertToViewFirst
=
false
}
}
}
func
canAnimate
(
view
:
UIView
,
isAppearing
:
Bool
)
->
Bool
{
public
func
resume
(
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
->
TimeInterval
{
guard
let
state
=
context
[
view
]
else
{
var
duration
:
TimeInterval
=
0
return
false
for
(
_
,
context
)
in
viewContexts
{
}
context
.
resume
(
elapsedTime
:
elapsedTime
,
isReversed
:
isReversed
)
duration
=
max
(
duration
,
context
.
duration
)
return
T
.
canAnimate
(
view
:
view
,
state
:
state
,
isAppearing
:
isAppearing
)
}
}
return
duration
}
func
animate
(
fromViews
:
[
UIView
],
toViews
:
[
UIView
])
->
TimeInterval
{
var
duration
:
TimeInterval
=
0
public
func
apply
(
state
:
MotionTargetState
,
to
view
:
UIView
)
{
if
let
context
=
viewContexts
[
view
]
{
if
insertToViewFirst
{
context
.
apply
(
state
:
state
)
for
v
in
toViews
{
animate
(
view
:
v
,
isAppearing
:
true
)
}
for
v
in
fromViews
{
animate
(
view
:
v
,
isAppearing
:
false
)
}
}
else
{
for
v
in
fromViews
{
animate
(
view
:
v
,
isAppearing
:
false
)
}
for
v
in
toViews
{
animate
(
view
:
v
,
isAppearing
:
true
)
}
}
for
v
in
viewToContexts
.
values
{
duration
=
max
(
duration
,
v
.
duration
)
}
return
duration
}
}
}
func
seek
(
to
elapsedTime
:
TimeInterval
)
{
public
func
canAnimate
(
view
:
UIView
,
isAppearing
:
Bool
)
->
Bool
{
for
v
in
viewToContexts
.
values
{
guard
let
state
=
context
[
view
]
else
{
return
false
}
v
.
seek
(
to
:
elapsedTime
)
return
ViewContext
.
canAnimate
(
view
:
view
,
state
:
state
,
isAppearing
:
isAppearing
)
}
}
public
func
animate
(
fromViews
:
[
UIView
],
toViews
:
[
UIView
])
->
TimeInterval
{
var
duration
:
TimeInterval
=
0
if
insertToViewFirst
{
for
v
in
toViews
{
animate
(
view
:
v
,
isAppearing
:
true
)
}
for
v
in
fromViews
{
animate
(
view
:
v
,
isAppearing
:
false
)
}
}
else
{
for
v
in
fromViews
{
animate
(
view
:
v
,
isAppearing
:
false
)
}
for
v
in
toViews
{
animate
(
view
:
v
,
isAppearing
:
true
)
}
}
}
for
viewContext
in
viewContexts
.
values
{
func
resume
(
at
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
->
TimeInterval
{
duration
=
max
(
duration
,
viewContext
.
duration
)
var
duration
:
TimeInterval
=
0
for
(
_
,
v
)
in
viewToContexts
{
v
.
resume
(
at
:
elapsedTime
,
isReversed
:
isReversed
)
duration
=
max
(
duration
,
v
.
duration
)
}
return
duration
}
}
return
duration
func
apply
(
state
:
MotionTargetState
,
to
view
:
UIView
)
{
}
guard
let
v
=
viewToContexts
[
view
]
else
{
return
func
animate
(
view
:
UIView
,
isAppearing
:
Bool
)
{
}
let
snapshot
=
context
.
snapshotView
(
for
:
view
)
let
viewContext
=
ViewContext
(
animator
:
self
,
snapshot
:
snapshot
,
targetState
:
context
[
view
]
!
)
v
.
apply
(
state
:
state
)
viewContexts
[
view
]
=
viewContext
viewContext
.
startAnimations
(
isAppearing
:
isAppearing
)
}
public
func
clean
()
{
for
vc
in
viewContexts
.
values
{
vc
.
clean
()
}
}
viewContexts
.
removeAll
()
insertToViewFirst
=
false
}
}
}
Sources/Animator/MotionHasInsertOrder.swift
0 → 100644
View file @
1bce1231
/*
* The MIT License (MIT)
*
* Copyright (C) 2017, Daniel Dahan and CosmicMind, Inc. <http://cosmicmind.com>.
* All rights reserved.
*
* Original Inspiration & Author
* Copyright (c) 2016 Luke Zhao <me@lkzhao.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
internal
protocol
MotionHasInsertOrder
:
class
{
/// A boolean indicating whether to insert the to-view first or not.
var
insertToViewFirst
:
Bool
{
get
set
}
}
Sources/Debug Plugin/MotionDebugPlugin.swift
View file @
1bce1231
...
@@ -59,7 +59,7 @@ public class MotionDebugPlugin: MotionPlugin {
...
@@ -59,7 +59,7 @@ public class MotionDebugPlugin: MotionPlugin {
return
.
infinity
return
.
infinity
}
}
public
override
func
resume
(
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
->
TimeInterval
{
public
override
func
resume
(
at
:
TimeInterval
,
isReversed
:
Bool
)
->
TimeInterval
{
guard
let
debugView
=
debugView
else
{
return
0.4
}
guard
let
debugView
=
debugView
else
{
return
0.4
}
debugView
.
delegate
=
nil
debugView
.
delegate
=
nil
...
...
Sources/Extensions/Motion+UIView.swift
View file @
1bce1231
...
@@ -28,6 +28,29 @@
...
@@ -28,6 +28,29 @@
import
UIKit
import
UIKit
internal
extension
UIView
{
func
optimizedDuration
(
fromPosition
:
CGPoint
,
toPosition
:
CGPoint
?,
size
:
CGSize
?,
transform
:
CATransform3D
?)
->
TimeInterval
{
let
fromPos
=
fromPosition
let
toPos
=
toPosition
??
fromPos
let
fromSize
=
(
layer
.
presentation
()
??
layer
)
.
bounds
.
size
let
toSize
=
size
??
fromSize
let
fromTransform
=
(
layer
.
presentation
()
??
layer
)
.
transform
let
toTransform
=
transform
??
fromTransform
let
realFromPos
=
CGPoint
.
zero
.
transform
(
fromTransform
)
+
fromPos
let
realToPos
=
CGPoint
.
zero
.
transform
(
toTransform
)
+
toPos
let
realFromSize
=
fromSize
.
transform
(
fromTransform
)
let
realToSize
=
toSize
.
transform
(
toTransform
)
let
movePoints
=
(
realFromPos
.
distance
(
realToPos
)
+
realFromSize
.
point
.
distance
(
realToSize
.
point
))
// duration is 0.2 @ 0 to 0.375 @ 500
let
duration
=
0.208
+
Double
(
movePoints
.
clamp
(
0
,
500
))
/
3000
return
duration
}
}
public
extension
UIView
{
public
extension
UIView
{
private
struct
AssociatedKeys
{
private
struct
AssociatedKeys
{
static
var
motionID
=
"motionID"
static
var
motionID
=
"motionID"
...
...
Sources/Motion.swift
View file @
1bce1231
...
@@ -203,7 +203,7 @@ internal extension Motion {
...
@@ -203,7 +203,7 @@ internal extension Motion {
insertToViewFirst
=
true
insertToViewFirst
=
true
}
}
for
animator
in
animators
{
for
animator
in
animators
{
if
let
animator
=
animator
as?
HasInsertOrder
{
if
let
animator
=
animator
as?
Motion
HasInsertOrder
{
animator
.
insertToViewFirst
=
insertToViewFirst
animator
.
insertToViewFirst
=
insertToViewFirst
}
}
}
}
...
...
Sources/MotionController.swift
View file @
1bce1231
...
@@ -50,11 +50,11 @@ public class MotionController: NSObject {
...
@@ -50,11 +50,11 @@ public class MotionController: NSObject {
let
elapsedTime
=
progress
*
totalDuration
let
elapsedTime
=
progress
*
totalDuration
if
interactive
{
if
interactive
{
for
animator
in
animators
{
for
animator
in
animators
{
animator
.
seek
To
(
elapsedTime
:
elapsedTime
)
animator
.
seek
(
to
:
elapsedTime
)
}
}
}
else
{
}
else
{
for
plugin
in
plugins
where
plugin
.
requirePerFrameCallback
{
for
plugin
in
plugins
where
plugin
.
requirePerFrameCallback
{
plugin
.
seek
To
(
elapsedTime
:
elapsedTime
)
plugin
.
seek
(
to
:
elapsedTime
)
}
}
}
}
}
}
...
@@ -156,8 +156,7 @@ public extension MotionController {
...
@@ -156,8 +156,7 @@ public extension MotionController {
}
}
var
maxTime
:
TimeInterval
=
0
var
maxTime
:
TimeInterval
=
0
for
animator
in
self
.
animators
{
for
animator
in
self
.
animators
{
maxTime
=
max
(
maxTime
,
animator
.
resume
(
elapsedTime
:
self
.
progress
*
self
.
totalDuration
,
maxTime
=
max
(
maxTime
,
animator
.
resume
(
at
:
self
.
progress
*
self
.
totalDuration
,
isReversed
:
false
))
isReversed
:
false
))
}
}
self
.
complete
(
after
:
maxTime
,
finishing
:
true
)
self
.
complete
(
after
:
maxTime
,
finishing
:
true
)
}
}
...
@@ -179,8 +178,7 @@ public extension MotionController {
...
@@ -179,8 +178,7 @@ public extension MotionController {
if
adjustedProgress
<
0
{
if
adjustedProgress
<
0
{
adjustedProgress
=
-
adjustedProgress
adjustedProgress
=
-
adjustedProgress
}
}
maxTime
=
max
(
maxTime
,
animator
.
resume
(
elapsedTime
:
adjustedProgress
*
self
.
totalDuration
,
maxTime
=
max
(
maxTime
,
animator
.
resume
(
at
:
adjustedProgress
*
self
.
totalDuration
,
isReversed
:
true
))
isReversed
:
true
))
}
}
self
.
complete
(
after
:
maxTime
,
finishing
:
false
)
self
.
complete
(
after
:
maxTime
,
finishing
:
false
)
}
}
...
...
Sources/MotionPlugin.swift
View file @
1bce1231
...
@@ -105,7 +105,7 @@ open class MotionPlugin: NSObject, MotionPreprocessor, MotionAnimator {
...
@@ -105,7 +105,7 @@ open class MotionPlugin: NSObject, MotionPreprocessor, MotionAnimator {
- Parameters:
- Parameters:
- elapsedTime: time of the animation to seek to.
- elapsedTime: time of the animation to seek to.
*/
*/
open
func
seek
To
(
elapsedTime
:
TimeInterval
)
{}
open
func
seek
(
to
elapsedTime
:
TimeInterval
)
{}
/**
/**
For supporting interactive animation only.
For supporting interactive animation only.
...
@@ -116,7 +116,7 @@ open class MotionPlugin: NSObject, MotionPreprocessor, MotionAnimator {
...
@@ -116,7 +116,7 @@ open class MotionPlugin: NSObject, MotionPreprocessor, MotionAnimator {
- elapsedTime: will be the same value since last `seekTo`
- elapsedTime: will be the same value since last `seekTo`
- reverse: a boolean value indicating whether or not the animation should reverse
- reverse: a boolean value indicating whether or not the animation should reverse
*/
*/
open
func
resume
(
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
->
TimeInterval
{
return
0
}
open
func
resume
(
at
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
->
TimeInterval
{
return
0
}
/**
/**
For supporting interactive animation only.
For supporting interactive animation only.
...
...
Sources/MotionTypes.swift
View file @
1bce1231
...
@@ -29,35 +29,86 @@
...
@@ -29,35 +29,86 @@
import
UIKit
import
UIKit
public
protocol
MotionPreprocessor
:
class
{
public
protocol
MotionPreprocessor
:
class
{
weak
var
context
:
MotionContext
!
{
get
set
}
weak
var
context
:
MotionContext
!
{
get
set
}
func
process
(
fromViews
:
[
UIView
],
toViews
:
[
UIView
])
func
process
(
fromViews
:
[
UIView
],
toViews
:
[
UIView
])
}
}
public
protocol
MotionAnimator
:
class
{
public
protocol
MotionAnimator
:
class
{
weak
var
context
:
MotionContext
!
{
get
set
}
/// A reference to a MotionContext.
func
canAnimate
(
view
:
UIView
,
isAppearing
:
Bool
)
->
Bool
weak
var
context
:
MotionContext
!
{
get
set
}
func
animate
(
fromViews
:
[
UIView
],
toViews
:
[
UIView
])
->
TimeInterval
func
clean
()
/// Cleans the contexts.
func
clean
()
func
seekTo
(
elapsedTime
:
TimeInterval
)
func
resume
(
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
->
TimeInterval
/**
func
apply
(
state
:
MotionTargetState
,
to
view
:
UIView
)
A function that determines if a view can be animated.
- Parameter view: A UIView.
- Parameter isAppearing: A boolean that determines whether the
view is appearing.
*/
func
canAnimate
(
view
:
UIView
,
isAppearing
:
Bool
)
->
Bool
/**
Animates the from-views to the to-views.
- Parameter fromViews: An Array of UIViews.
- Parameter toViews: An Array of UIViews.
- Returns: A TimeInterval.
*/
func
animate
(
fromViews
:
[
UIView
],
toViews
:
[
UIView
])
->
TimeInterval
/**
Moves the view's animation to the given elapsed time.
- Parameter to elapsedTime: A TimeInterval.
*/
func
seek
(
to
elapsedTime
:
TimeInterval
)
/**
Resumes the animation with a given elapsed time and
optional reversed boolean.
- Parameter at elapsedTime: A TimeInterval.
- Parameter isReversed: A boolean to reverse the animation
or not.
*/
func
resume
(
at
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
->
TimeInterval
/**
Applies the given state to the given view.
- Parameter state: A MotionTargetState.
- Parameter to view: A UIView.
*/
func
apply
(
state
:
MotionTargetState
,
to
view
:
UIView
)
}
}
public
protocol
MotionProgressUpdateObserver
{
public
protocol
MotionProgressUpdateObserver
{
func
motionDidUpdateProgress
(
progress
:
Double
)
func
motionDidUpdateProgress
(
progress
:
Double
)
}
}
@objc
public
protocol
MotionViewControllerDelegate
{
@objc(MotionViewControllerDelegate)
@objc
optional
func
motionWillStartAnimatingFrom
(
viewController
:
UIViewController
)
public
protocol
MotionViewControllerDelegate
{
@objc
optional
func
motionDidEndAnimatingFrom
(
viewController
:
UIViewController
)
@objc
@objc
optional
func
motionDidCancelAnimatingFrom
(
viewController
:
UIViewController
)
optional
func
motionWillStartAnimatingFrom
(
viewController
:
UIViewController
)
@objc
optional
func
motionDidEndAnimatingFrom
(
viewController
:
UIViewController
)
@objc
optional
func
motionDidCancelAnimatingFrom
(
viewController
:
UIViewController
)
@objc
optional
func
motionWillStartTransition
()
@objc
@objc
optional
func
motionDidEndTransition
()
optional
func
motionWillStartTransition
()
@objc
optional
func
motionDidCancelTransition
()
@objc
optional
func
motionDidEndTransition
()
@objc
optional
func
motionDidCancelTransition
()
@objc
optional
func
motionWillStartAnimatingTo
(
viewController
:
UIViewController
)
@objc
@objc
optional
func
motionDidEndAnimatingTo
(
viewController
:
UIViewController
)
optional
func
motionWillStartAnimatingTo
(
viewController
:
UIViewController
)
@objc
optional
func
motionDidCancelAnimatingTo
(
viewController
:
UIViewController
)
@objc
optional
func
motionDidEndAnimatingTo
(
viewController
:
UIViewController
)
@objc
optional
func
motionDidCancelAnimatingTo
(
viewController
:
UIViewController
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment