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
2caa4eb1
Unverified
Commit
2caa4eb1
authored
Jun 05, 2017
by
Daniel Dahan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
initial clean up for MotionCoreAnimationViewContext completed
parent
97383774
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
234 additions
and
207 deletions
+234
-207
Sources/Animator/MotionCoreAnimationViewContext.swift
+234
-207
No files found.
Sources/Animator/MotionCoreAnimationViewContext.swift
View file @
2caa4eb1
...
@@ -43,13 +43,11 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
...
@@ -43,13 +43,11 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
/// Layer which holds the overlay.
/// Layer which holds the overlay.
fileprivate
var
overlayLayer
:
CALayer
?
fileprivate
var
overlayLayer
:
CALayer
?
/**
override
func
clean
()
{
Determines whether a view can be animated.
super
.
clean
()
- Parameter view: A UIView.
overlayLayer
=
nil
- Parameter state: A MotionTargetState.
}
- Parameter isAppearing: A boolean indicating whether or not the
view is going to appear.
*/
override
class
func
canAnimate
(
view
:
UIView
,
state
:
MotionTargetState
,
isAppearing
:
Bool
)
->
Bool
{
override
class
func
canAnimate
(
view
:
UIView
,
state
:
MotionTargetState
,
isAppearing
:
Bool
)
->
Bool
{
return
nil
!=
state
.
position
||
return
nil
!=
state
.
position
||
nil
!=
state
.
size
||
nil
!=
state
.
size
||
...
@@ -69,11 +67,73 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
...
@@ -69,11 +67,73 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
state
.
forceAnimate
state
.
forceAnimate
}
}
override
func
apply
(
state
:
MotionTargetState
)
{
let
ts
=
viewState
(
targetState
:
state
)
for
(
key
,
targetValue
)
in
ts
{
if
nil
==
transitionStates
[
key
]
{
let
current
=
currentValue
(
for
:
key
)
transitionStates
[
key
]
=
(
current
,
current
)
}
animate
(
key
:
key
,
beginTime
:
0
,
fromValue
:
targetValue
,
toValue
:
targetValue
)
}
}
override
func
resume
(
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
{
for
(
key
,
(
fromValue
,
toValue
))
in
transitionStates
{
transitionStates
[
key
]
=
(
currentValue
(
for
:
key
),
!
isReversed
?
toValue
:
fromValue
)
}
targetState
.
duration
=
isReversed
?
elapsedTime
-
targetState
.
delay
:
duration
-
elapsedTime
animate
(
delay
:
max
(
0
,
targetState
.
delay
-
elapsedTime
))
}
override
func
seek
(
to
elapsedTime
:
TimeInterval
)
{
seek
(
layer
:
snapshot
.
layer
,
elapsedTime
:
elapsedTime
)
if
let
v
=
contentLayer
{
seek
(
layer
:
v
,
elapsedTime
:
elapsedTime
)
}
if
let
v
=
overlayLayer
{
seek
(
layer
:
v
,
elapsedTime
:
elapsedTime
)
}
}
override
func
startAnimations
(
isAppearing
:
Bool
)
{
if
let
beginState
=
targetState
.
beginState
?
.
state
{
let
appeared
=
viewState
(
targetState
:
beginState
)
for
(
k
,
v
)
in
appeared
{
snapshot
.
layer
.
setValue
(
v
,
forKeyPath
:
k
)
}
if
let
(
k
,
v
)
=
beginState
.
overlay
{
let
overlay
=
getOverlayLayer
()
overlay
.
backgroundColor
=
k
overlay
.
opacity
=
Float
(
v
)
}
}
let
disappeared
=
viewState
(
targetState
:
targetState
)
for
(
k
,
v
)
in
disappeared
{
let
isAppearingState
=
currentValue
(
for
:
k
)
let
toValue
=
isAppearing
?
isAppearingState
:
v
let
fromValue
=
!
isAppearing
?
isAppearingState
:
v
transitionStates
[
k
]
=
(
fromValue
,
toValue
)
}
animate
(
delay
:
targetState
.
delay
)
}
}
extension
MotionCoreAnimationViewContext
{
/**
/**
Lazy loads the overlay layer.
Lazy loads the overlay layer.
- Returns: A CALayer.
- Returns: A CALayer.
*/
*/
func
getOverlayLayer
()
->
CALayer
{
f
ileprivate
f
unc
getOverlayLayer
()
->
CALayer
{
if
nil
==
overlayLayer
{
if
nil
==
overlayLayer
{
overlayLayer
=
CALayer
()
overlayLayer
=
CALayer
()
overlayLayer
!.
frame
=
snapshot
.
bounds
overlayLayer
!.
frame
=
snapshot
.
bounds
...
@@ -89,7 +149,7 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
...
@@ -89,7 +149,7 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
- Parameter for key: A String.
- Parameter for key: A String.
- Returns: An optional String.
- Returns: An optional String.
*/
*/
func
overlayKey
(
for
key
:
String
)
->
String
?
{
f
ileprivate
f
unc
overlayKey
(
for
key
:
String
)
->
String
?
{
guard
key
.
hasPrefix
(
"overlay."
)
else
{
guard
key
.
hasPrefix
(
"overlay."
)
else
{
return
nil
return
nil
}
}
...
@@ -100,11 +160,11 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
...
@@ -100,11 +160,11 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
}
}
/**
/**
Retrieves the current value for a given key.
Retrieves the current value for a given key.
- Parameter for key: A String.
- Parameter for key: A String.
- Returns: An optional Any value.
- Returns: An optional Any value.
*/
*/
func
currentValue
(
for
key
:
String
)
->
Any
?
{
f
ileprivate
f
unc
currentValue
(
for
key
:
String
)
->
Any
?
{
if
let
key
=
overlayKey
(
for
:
key
)
{
if
let
key
=
overlayKey
(
for
:
key
)
{
return
overlayLayer
?
.
value
(
forKeyPath
:
key
)
return
overlayLayer
?
.
value
(
forKeyPath
:
key
)
}
}
...
@@ -117,35 +177,35 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
...
@@ -117,35 +177,35 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
}
}
/**
/**
Retrieves the animation for a given key.
Retrieves the animation for a given key.
- Parameter key: String.
- Parameter key: String.
- Parameter beginTime: A TimeInterval.
- Parameter beginTime: A TimeInterval.
- Parameter fromValue: An optional Any value.
- Parameter fromValue: An optional Any value.
- Parameter toValue: An optional Any value.
- Parameter toValue: An optional Any value.
- Parameter ignoreArc: A Boolean value to ignore an arc position.
- Parameter ignoreArc: A Boolean value to ignore an arc position.
*/
*/
func
getAnimation
(
key
:
String
,
beginTime
:
TimeInterval
,
fromValue
:
Any
?,
toValue
:
Any
?,
ignoreArc
:
Bool
=
false
)
->
CAPropertyAnimation
{
f
ileprivate
f
unc
getAnimation
(
key
:
String
,
beginTime
:
TimeInterval
,
fromValue
:
Any
?,
toValue
:
Any
?,
ignoreArc
:
Bool
=
false
)
->
CAPropertyAnimation
{
let
key
=
overlayKey
(
for
:
key
)
??
key
let
key
=
overlayKey
(
for
:
key
)
??
key
let
anim
:
CAPropertyAnimation
let
anim
:
CAPropertyAnimation
if
!
ignoreArc
,
"position"
==
key
,
let
arcIntensity
=
targetState
.
arc
,
if
!
ignoreArc
,
"position"
==
key
,
let
arcIntensity
=
targetState
.
arc
,
let
fromPos
=
(
fromValue
as?
NSValue
)?
.
cgPointValue
,
let
fromPos
=
(
fromValue
as?
NSValue
)?
.
cgPointValue
,
let
toPos
=
(
toValue
as?
NSValue
)?
.
cgPointValue
,
let
toPos
=
(
toValue
as?
NSValue
)?
.
cgPointValue
,
abs
(
fromPos
.
x
-
toPos
.
x
)
>=
1
,
abs
(
fromPos
.
y
-
toPos
.
y
)
>=
1
{
abs
(
fromPos
.
x
-
toPos
.
x
)
>=
1
,
abs
(
fromPos
.
y
-
toPos
.
y
)
>=
1
{
let
a
=
CAKeyframeAnimation
(
keyPath
:
key
)
let
a
=
CAKeyframeAnimation
(
keyPath
:
key
)
let
path
=
CGMutablePath
()
let
path
=
CGMutablePath
()
let
maxControl
=
fromPos
.
y
>
toPos
.
y
?
CGPoint
(
x
:
toPos
.
x
,
y
:
fromPos
.
y
)
:
CGPoint
(
x
:
fromPos
.
x
,
y
:
toPos
.
y
)
let
maxControl
=
fromPos
.
y
>
toPos
.
y
?
CGPoint
(
x
:
toPos
.
x
,
y
:
fromPos
.
y
)
:
CGPoint
(
x
:
fromPos
.
x
,
y
:
toPos
.
y
)
let
minControl
=
(
toPos
-
fromPos
)
/
2
+
fromPos
let
minControl
=
(
toPos
-
fromPos
)
/
2
+
fromPos
path
.
move
(
to
:
fromPos
)
path
.
move
(
to
:
fromPos
)
path
.
addQuadCurve
(
to
:
toPos
,
control
:
minControl
+
(
maxControl
-
minControl
)
*
arcIntensity
)
path
.
addQuadCurve
(
to
:
toPos
,
control
:
minControl
+
(
maxControl
-
minControl
)
*
arcIntensity
)
a
.
values
=
[
fromValue
!
,
toValue
!
]
a
.
values
=
[
fromValue
!
,
toValue
!
]
a
.
path
=
path
a
.
path
=
path
a
.
duration
=
duration
a
.
duration
=
duration
a
.
timingFunctions
=
[
timingFunction
]
a
.
timingFunctions
=
[
timingFunction
]
anim
=
a
anim
=
a
}
else
if
#available(iOS 9.0, *)
,
"cornerRadius"
!=
key
,
let
(
stiffness
,
damping
)
=
targetState
.
spring
{
}
else
if
#available(iOS 9.0, *)
,
"cornerRadius"
!=
key
,
let
(
stiffness
,
damping
)
=
targetState
.
spring
{
let
a
=
CASpringAnimation
(
keyPath
:
key
)
let
a
=
CASpringAnimation
(
keyPath
:
key
)
...
@@ -165,14 +225,14 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
...
@@ -165,14 +225,14 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
anim
=
a
anim
=
a
}
}
anim
.
fillMode
=
kCAFillModeBoth
anim
.
fillMode
=
kCAFillModeBoth
anim
.
isRemovedOnCompletion
=
false
anim
.
isRemovedOnCompletion
=
false
anim
.
beginTime
=
beginTime
anim
.
beginTime
=
beginTime
return
anim
return
anim
}
}
/**
/**
Retrieves the duration of an animation, including the
Retrieves the duration of an animation, including the
duration of the animation and the initial delay.
duration of the animation and the initial delay.
...
@@ -182,214 +242,181 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
...
@@ -182,214 +242,181 @@ internal class MotionCoreAnimationViewContext: MotionAnimatorViewContext {
- Parameter toValue: A optional Any value.
- Parameter toValue: A optional Any value.
- Returns: A TimeInterval.
- Returns: A TimeInterval.
*/
*/
func
animate
(
key
:
String
,
beginTime
:
TimeInterval
,
fromValue
:
Any
?,
toValue
:
Any
?)
->
TimeInterval
{
@discardableResult
fileprivate
func
animate
(
key
:
String
,
beginTime
:
TimeInterval
,
fromValue
:
Any
?,
toValue
:
Any
?)
->
TimeInterval
{
let
anim
=
getAnimation
(
key
:
key
,
beginTime
:
beginTime
,
fromValue
:
fromValue
,
toValue
:
toValue
)
let
anim
=
getAnimation
(
key
:
key
,
beginTime
:
beginTime
,
fromValue
:
fromValue
,
toValue
:
toValue
)
if
let
overlayKey
=
overlayKey
(
for
:
key
)
{
if
let
overlayKey
=
overlayKey
(
for
:
key
)
{
getOverlayLayer
()
.
add
(
anim
,
forKey
:
overlayKey
)
getOverlayLayer
()
.
add
(
anim
,
forKey
:
overlayKey
)
}
else
{
}
else
{
snapshot
.
layer
.
add
(
anim
,
forKey
:
key
)
snapshot
.
layer
.
add
(
anim
,
forKey
:
key
)
switch
key
{
switch
key
{
case
"cornerRadius"
,
"contentsRect"
,
"contentsScale"
:
case
"cornerRadius"
,
"contentsRect"
,
"contentsScale"
:
contentLayer
?
.
add
(
anim
,
forKey
:
key
)
contentLayer
?
.
add
(
anim
,
forKey
:
key
)
overlayLayer
?
.
add
(
anim
,
forKey
:
key
)
overlayLayer
?
.
add
(
anim
,
forKey
:
key
)
case
"bounds.size"
:
case
"bounds.size"
:
let
fromSize
=
(
fromValue
as?
NSValue
)
!.
cgSizeValue
guard
let
fs
=
(
fromValue
as?
NSValue
)?
.
cgSizeValue
else
{
let
toSize
=
(
toValue
as?
NSValue
)
!.
cgSizeValue
return
0
}
guard
let
ts
=
(
toValue
as?
NSValue
)?
.
cgSizeValue
else
{
return
0
}
// for the snapshotView(UIReplicantView): there is a
// for the snapshotView(UIReplicantView): there is a
// subview(UIReplicantContentView) that is hosting the real snapshot image.
// subview(UIReplicantContentView) that is hosting the real snapshot image.
// because we are using CAAnimations and not UIView animations,
// because we are using CAAnimations and not UIView animations,
// The snapshotView will not layout during animations.
// The snapshotView will not layout during animations.
// we have to add two more animations to manually layout the content view.
// we have to add two more animations to manually layout the content view.
let
f
romPosn
=
NSValue
(
cgPoint
:
fromSize
.
center
)
let
f
pn
=
NSValue
(
cgPoint
:
fs
.
center
)
let
t
oPosn
=
NSValue
(
cgPoint
:
toSize
.
center
)
let
t
pn
=
NSValue
(
cgPoint
:
ts
.
center
)
let
positionAnim
=
getAnimation
(
key
:
"position"
,
beginTime
:
0
,
fromValue
:
fromPosn
,
toValue
:
toPos
n
,
ignoreArc
:
true
)
let
a
=
getAnimation
(
key
:
"position"
,
beginTime
:
0
,
fromValue
:
fpn
,
toValue
:
tp
n
,
ignoreArc
:
true
)
positionAnim
.
beginTime
=
anim
.
beginTime
a
.
beginTime
=
anim
.
beginTime
positionAnim
.
timingFunction
=
anim
.
timingFunction
a
.
timingFunction
=
anim
.
timingFunction
positionAnim
.
duration
=
anim
.
duration
a
.
duration
=
anim
.
duration
contentLayer
?
.
add
(
positionAnim
,
forKey
:
"position"
)
contentLayer
?
.
add
(
a
,
forKey
:
"position"
)
contentLayer
?
.
add
(
anim
,
forKey
:
key
)
contentLayer
?
.
add
(
anim
,
forKey
:
key
)
overlayLayer
?
.
add
(
positionAnim
,
forKey
:
"position"
)
overlayLayer
?
.
add
(
a
,
forKey
:
"position"
)
overlayLayer
?
.
add
(
anim
,
forKey
:
key
)
overlayLayer
?
.
add
(
anim
,
forKey
:
key
)
default
:
break
default
:
break
}
}
}
}
return
anim
.
duration
+
anim
.
beginTime
-
beginTime
return
anim
.
duration
+
anim
.
beginTime
-
beginTime
}
}
func
animate
(
delay
:
TimeInterval
)
{
/**
if
let
tf
=
targetState
.
timingFunction
{
Animates the contentLayer and overlayLayer with a given delay.
timingFunction
=
tf
- Parameter delay: A TimeInterval.
}
*/
fileprivate
func
animate
(
delay
:
TimeInterval
)
{
duration
=
targetState
.
duration
!
if
let
v
=
targetState
.
timingFunction
{
timingFunction
=
v
let
beginTime
=
currentTime
+
delay
}
var
finalDuration
:
TimeInterval
=
duration
for
(
key
,
(
fromValue
,
toValue
))
in
transitionStates
{
if
let
v
=
targetState
.
duration
{
let
neededTime
=
animate
(
key
:
key
,
beginTime
:
beginTime
,
fromValue
:
fromValue
,
toValue
:
toValue
)
duration
=
v
finalDuration
=
max
(
finalDuration
,
neededTime
+
delay
)
}
}
let
beginTime
=
currentTime
+
delay
duration
=
finalDuration
}
var
finalDuration
:
TimeInterval
=
duration
/**
for
(
key
,
(
fromValue
,
toValue
))
in
transitionStates
{
- Returns: a CALayer [keyPath:value] map for animation
let
neededTime
=
animate
(
key
:
key
,
beginTime
:
beginTime
,
fromValue
:
fromValue
,
toValue
:
toValue
)
*/
finalDuration
=
max
(
finalDuration
,
neededTime
+
delay
)
func
viewState
(
targetState
:
MotionTargetState
)
->
[
String
:
Any
?]
{
}
var
targetState
=
targetState
var
rtn
=
[
String
:
Any
?]()
duration
=
finalDuration
if
let
size
=
targetState
.
size
{
if
targetState
.
useScaleBasedSizeChange
??
self
.
targetState
.
useScaleBasedSizeChange
??
false
{
let
currentSize
=
snapshot
.
bounds
.
size
targetState
.
append
(
.
scale
(
x
:
size
.
width
/
currentSize
.
width
,
y
:
size
.
height
/
currentSize
.
height
))
}
else
{
rtn
[
"bounds.size"
]
=
NSValue
(
cgSize
:
size
)
}
}
if
let
position
=
targetState
.
position
{
rtn
[
"position"
]
=
NSValue
(
cgPoint
:
position
)
}
if
let
opacity
=
targetState
.
opacity
,
!
(
snapshot
is
UIVisualEffectView
)
{
rtn
[
"opacity"
]
=
NSNumber
(
value
:
opacity
)
}
if
let
cornerRadius
=
targetState
.
cornerRadius
{
rtn
[
"cornerRadius"
]
=
NSNumber
(
value
:
cornerRadius
.
native
)
}
if
let
backgroundColor
=
targetState
.
backgroundColor
{
rtn
[
"backgroundColor"
]
=
backgroundColor
}
if
let
zPosition
=
targetState
.
zPosition
{
rtn
[
"zPosition"
]
=
NSNumber
(
value
:
zPosition
.
native
)
}
if
let
borderWidth
=
targetState
.
borderWidth
{
rtn
[
"borderWidth"
]
=
NSNumber
(
value
:
borderWidth
.
native
)
}
if
let
borderColor
=
targetState
.
borderColor
{
rtn
[
"borderColor"
]
=
borderColor
}
if
let
masksToBounds
=
targetState
.
masksToBounds
{
rtn
[
"masksToBounds"
]
=
masksToBounds
}
if
targetState
.
displayShadow
{
if
let
shadowColor
=
targetState
.
shadowColor
{
rtn
[
"shadowColor"
]
=
shadowColor
}
if
let
shadowRadius
=
targetState
.
shadowRadius
{
rtn
[
"shadowRadius"
]
=
NSNumber
(
value
:
shadowRadius
.
native
)
}
if
let
shadowOpacity
=
targetState
.
shadowOpacity
{
rtn
[
"shadowOpacity"
]
=
NSNumber
(
value
:
shadowOpacity
)
}
if
let
shadowPath
=
targetState
.
shadowPath
{
rtn
[
"shadowPath"
]
=
shadowPath
}
if
let
shadowOffset
=
targetState
.
shadowOffset
{
rtn
[
"shadowOffset"
]
=
NSValue
(
cgSize
:
shadowOffset
)
}
}
if
let
contentsRect
=
targetState
.
contentsRect
{
rtn
[
"contentsRect"
]
=
NSValue
(
cgRect
:
contentsRect
)
}
if
let
contentsScale
=
targetState
.
contentsScale
{
rtn
[
"contentsScale"
]
=
NSNumber
(
value
:
contentsScale
.
native
)
}
if
let
transform
=
targetState
.
transform
{
rtn
[
"transform"
]
=
NSValue
(
caTransform3D
:
transform
)
}
if
let
(
color
,
opacity
)
=
targetState
.
overlay
{
rtn
[
"overlay.backgroundColor"
]
=
color
rtn
[
"overlay.opacity"
]
=
NSNumber
(
value
:
opacity
.
native
)
}
return
rtn
}
override
func
apply
(
state
:
MotionTargetState
)
{
let
targetState
=
viewState
(
targetState
:
state
)
for
(
key
,
targetValue
)
in
targetState
{
if
self
.
transitionStates
[
key
]
==
nil
{
let
current
=
currentValue
(
for
:
key
)
self
.
transitionStates
[
key
]
=
(
current
,
current
)
}
_
=
animate
(
key
:
key
,
beginTime
:
0
,
fromValue
:
targetValue
,
toValue
:
targetValue
)
}
}
override
func
resume
(
elapsedTime
:
TimeInterval
,
isReversed
:
Bool
)
{
for
(
key
,
(
fromValue
,
toValue
))
in
transitionStates
{
let
realToValue
=
!
isReversed
?
toValue
:
fromValue
let
realFromValue
=
currentValue
(
for
:
key
)
transitionStates
[
key
]
=
(
realFromValue
,
realToValue
)
}
// we need to update the duration to reflect current state
targetState
.
duration
=
isReversed
?
elapsedTime
-
targetState
.
delay
:
duration
-
elapsedTime
let
realDelay
=
max
(
0
,
targetState
.
delay
-
elapsedTime
)
animate
(
delay
:
realDelay
)
}
func
seek
(
layer
:
CALayer
,
elapsedTime
:
TimeInterval
)
{
let
timeOffset
=
elapsedTime
-
targetState
.
delay
for
(
key
,
anim
)
in
layer
.
animations
{
anim
.
speed
=
0
anim
.
timeOffset
=
max
(
0
,
min
(
anim
.
duration
-
0.01
,
timeOffset
))
layer
.
removeAnimation
(
forKey
:
key
)
layer
.
add
(
anim
,
forKey
:
key
)
}
}
override
func
seek
(
to
elapsedTime
:
TimeInterval
)
{
seek
(
layer
:
snapshot
.
layer
,
elapsedTime
:
elapsedTime
)
if
let
contentLayer
=
contentLayer
{
seek
(
layer
:
contentLayer
,
elapsedTime
:
elapsedTime
)
}
if
let
overlayLayer
=
overlayLayer
{
seek
(
layer
:
overlayLayer
,
elapsedTime
:
elapsedTime
)
}
}
}
/**
override
func
clean
()
{
Constructs a map of key paths to animation values.
super
.
clean
()
- Parameter targetState state: A MotionTargetState.
overlayLayer
=
nil
- Returns: A map of key paths to animation values.
}
*/
fileprivate
func
viewState
(
targetState
ts
:
MotionTargetState
)
->
[
String
:
Any
?]
{
override
func
startAnimations
(
isAppearing
:
Bool
)
{
var
ts
=
ts
if
let
beginState
=
targetState
.
beginState
?
.
state
{
var
values
=
[
String
:
Any
?]()
let
appeared
=
viewState
(
targetState
:
beginState
)
for
(
key
,
value
)
in
appeared
{
if
let
size
=
ts
.
size
{
snapshot
.
layer
.
setValue
(
value
,
forKeyPath
:
key
)
if
ts
.
useScaleBasedSizeChange
??
targetState
.
useScaleBasedSizeChange
??
false
{
}
let
currentSize
=
snapshot
.
bounds
.
size
if
let
(
color
,
opacity
)
=
beginState
.
overlay
{
ts
.
append
(
.
scale
(
x
:
size
.
width
/
currentSize
.
width
,
y
:
size
.
height
/
currentSize
.
height
))
let
overlay
=
getOverlayLayer
()
overlay
.
backgroundColor
=
color
}
else
{
overlay
.
opacity
=
Float
(
opacity
)
values
[
"bounds.size"
]
=
NSValue
(
cgSize
:
size
)
}
}
}
if
let
position
=
ts
.
position
{
values
[
"position"
]
=
NSValue
(
cgPoint
:
position
)
}
if
let
opacity
=
ts
.
opacity
,
!
(
snapshot
is
UIVisualEffectView
)
{
values
[
"opacity"
]
=
NSNumber
(
value
:
opacity
)
}
if
let
cornerRadius
=
ts
.
cornerRadius
{
values
[
"cornerRadius"
]
=
NSNumber
(
value
:
cornerRadius
.
native
)
}
if
let
backgroundColor
=
ts
.
backgroundColor
{
values
[
"backgroundColor"
]
=
backgroundColor
}
if
let
zPosition
=
ts
.
zPosition
{
values
[
"zPosition"
]
=
NSNumber
(
value
:
zPosition
.
native
)
}
if
let
borderWidth
=
ts
.
borderWidth
{
values
[
"borderWidth"
]
=
NSNumber
(
value
:
borderWidth
.
native
)
}
if
let
borderColor
=
ts
.
borderColor
{
values
[
"borderColor"
]
=
borderColor
}
if
let
masksToBounds
=
ts
.
masksToBounds
{
values
[
"masksToBounds"
]
=
masksToBounds
}
if
ts
.
displayShadow
{
if
let
shadowColor
=
ts
.
shadowColor
{
values
[
"shadowColor"
]
=
shadowColor
}
if
let
shadowRadius
=
ts
.
shadowRadius
{
values
[
"shadowRadius"
]
=
NSNumber
(
value
:
shadowRadius
.
native
)
}
if
let
shadowOpacity
=
ts
.
shadowOpacity
{
values
[
"shadowOpacity"
]
=
NSNumber
(
value
:
shadowOpacity
)
}
if
let
shadowPath
=
ts
.
shadowPath
{
values
[
"shadowPath"
]
=
shadowPath
}
if
let
shadowOffset
=
ts
.
shadowOffset
{
values
[
"shadowOffset"
]
=
NSValue
(
cgSize
:
shadowOffset
)
}
}
if
let
contentsRect
=
ts
.
contentsRect
{
values
[
"contentsRect"
]
=
NSValue
(
cgRect
:
contentsRect
)
}
if
let
contentsScale
=
ts
.
contentsScale
{
values
[
"contentsScale"
]
=
NSNumber
(
value
:
contentsScale
.
native
)
}
if
let
transform
=
ts
.
transform
{
values
[
"transform"
]
=
NSValue
(
caTransform3D
:
transform
)
}
if
let
(
color
,
opacity
)
=
ts
.
overlay
{
values
[
"overlay.backgroundColor"
]
=
color
values
[
"overlay.opacity"
]
=
NSNumber
(
value
:
opacity
.
native
)
}
return
values
}
}
let
disappeared
=
viewState
(
targetState
:
targetState
)
fileprivate
func
seek
(
layer
:
CALayer
,
elapsedTime
:
TimeInterval
)
{
let
timeOffset
=
elapsedTime
-
targetState
.
delay
for
(
key
,
disappearedState
)
in
disappeared
{
for
(
key
,
anim
)
in
layer
.
animations
{
let
isAppearingState
=
currentValue
(
for
:
key
)
anim
.
speed
=
0
let
toValue
=
isAppearing
?
isAppearingState
:
disappearedState
anim
.
timeOffset
=
max
(
0
,
min
(
anim
.
duration
-
0.01
,
timeOffset
))
let
fromValue
=
!
isAppearing
?
isAppearingState
:
disappearedState
layer
.
removeAnimation
(
forKey
:
key
)
transitionStates
[
key
]
=
(
fromValue
,
toValue
)
layer
.
add
(
anim
,
forKey
:
key
)
}
}
}
animate
(
delay
:
targetState
.
delay
)
}
}
}
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