Más contenido relacionado La actualidad más candente (20) Similar a Александр Зимин – Анимация как средство самовыражения (20) Александр Зимин – Анимация как средство самовыражения11. 11
Timer.scheduledTimer(withTimeInterval: 1 / 60, repeats: true)
{ (_) in
self.applyAnimationStep()
}
displayLink = CADisplayLink(target: self, selector:
#selector(applyAnimationStep))
displayLink.add(to: RunLoop.current, forMode:
RunLoopMode.defaultRunLoopMode)
18. 18
• Work with CALayer’s
• Shared for iOS/macOS
• Unfamiliar syntax
• Powerfull
19. 19
let animation = CABasicAnimation(keyPath: "position.x")
animation.duration = 1
animation.fromValue = animationView.layer.position.x
animation.toValue = 50
animationView.layer.add(animation, forKey: "name")
animationView.layer.position.x = 50
20. 20
let animation = CABasicAnimation(keyPath: "position.x")
animation.duration = 1
animation.fromValue = animationView.layer.position.x
animation.toValue = 50
animationView.layer.add(animation, forKey: "name")
animationView.layer.position.x = 50
29. 29
animation = CABasicAnimation(keyPath: "position.y")
animation.duration = 2
animation.fromValue = label.layer.position.y
animation.toValue = 30
label.layer.add(animation, forKey: "animation2")
label.layer.speed = 0
label.layer.position.y = 30
36. 36
let firstPath = UIBezierPath(
roundedRect: CGRect(x: 100, y: 100, width: 100, height: 100),
byRoundingCorners: [.bottomRight, .topRight],
cornerRadii: CGSize(width: 30, height: 30)
)
let secondPath = UIBezierPath(
rect: CGRect(x: 100, y: 100, width: 100, height: 100)
)
37. 37
let firstPath = UIBezierPath(
roundedRect: CGRect(x: 100, y: 100, width: 100, height: 100),
byRoundingCorners: [.bottomRight, .topRight],
cornerRadii: CGSize(width: 30, height: 30)
)
let secondPath = UIBezierPath(
rect: CGRect(x: 100, y: 100, width: 100, height: 100)
)
40. 40
let firstPath = UIBezierPath()
firstPath.move(to: CGPoint(x: 0, y: 0))
firstPath.addLine(to: CGPoint(x: 60, y: 0))
firstPath.addQuadCurve(to: CGPoint(x: 100, y: 40), controlPoint:
CGPoint(x: 100, y: 0))
firstPath.addLine(to: CGPoint(x: 100, y: 60))
firstPath.addQuadCurve(to: CGPoint(x: 60, y: 100), controlPoint:
CGPoint(x: 100, y: 100))
firstPath.addLine(to: CGPoint(x: 0, y: 100))
firstPath.addLine(to: CGPoint(x: 0, y: 0))
41. let firstPath = UIBezierPath()
firstPath.move(to: CGPoint(x: 0, y: 0))
firstPath.addLine(to: CGPoint(x: 60, y: 0))
firstPath.addQuadCurve(to: CGPoint(x: 100, y: 40), controlPoint:
CGPoint(x: 100, y: 0))
firstPath.addLine(to: CGPoint(x: 100, y: 60))
firstPath.addQuadCurve(to: CGPoint(x: 60, y: 100), controlPoint:
CGPoint(x: 100, y: 100))
firstPath.addLine(to: CGPoint(x: 0, y: 100))
firstPath.addLine(to: CGPoint(x: 0, y: 0))
41
43. 43
let secondPath = UIBezierPath()
secondPath.move(to: CGPoint(x: 0, y: 0))
secondPath.addLine(to: CGPoint(x: 100, y: 0))
secondPath.addLine(to: CGPoint(x: 100, y: 0))
secondPath.addLine(to: CGPoint(x: 100, y: 100))
secondPath.addLine(to: CGPoint(x: 100, y: 100))
secondPath.addLine(to: CGPoint(x: 0, y: 100))
secondPath.addLine(to: CGPoint(x: 0, y: 0))
44. 44
let secondPath = UIBezierPath()
secondPath.move(to: CGPoint(x: 0, y: 0))
secondPath.addLine(to: CGPoint(x: 100, y: 0))
secondPath.addLine(to: CGPoint(x: 100, y: 0))
secondPath.addLine(to: CGPoint(x: 100, y: 100))
secondPath.addLine(to: CGPoint(x: 100, y: 100))
secondPath.addLine(to: CGPoint(x: 0, y: 100))
secondPath.addLine(to: CGPoint(x: 0, y: 0))
50. 50
let differenceInSize = label.font.pointSize /
anotherLabel.font.pointSize
self.anotherLabel.transform = CGAffineTransform(scaleX:
differenceInSize, y: differenceInSize)
self.anotherLabel.center = self.label.center
self.label.alpha = 1
self.anotherLabel.alpha = 0
51. 51
let differenceInSize = label.font.pointSize /
anotherLabel.font.pointSize
self.anotherLabel.transform = CGAffineTransform(scaleX:
differenceInSize, y: differenceInSize)
self.anotherLabel.center = self.label.center
self.label.alpha = 1
self.anotherLabel.alpha = 0
a a
52. 52
let differenceInSize = label.font.pointSize /
anotherLabel.font.pointSize
self.anotherLabel.transform = CGAffineTransform(scaleX:
differenceInSize, y: differenceInSize)
self.anotherLabel.center = self.label.center
self.label.alpha = 1
self.anotherLabel.alpha = 0
53. 53
propertyAnimation = UIViewPropertyAnimator(duration: 0.5,
curve: .easeIn) {
self.label.alpha = 0
self.anotherLabel.alpha = 1
self.label.center.y = 50
self.anotherLabel.center.y = 50
self.label.transform = CGAffineTransform(scaleX: 1 /
differenceInSize, y: 1 / differenceInSize)
self.anotherLabel.transform = CGAffineTransform.identity
}
56. 56
• var isReversed: Bool { get set }
• var fractionComplete: CGFloat { get set }
• func continueAnimation(
withTimingParameters parameters:
UITimingCurveProvider?,
durationFactor: CGFloat)
62. 62
opacity = 1 -> 0.2
duration = 2
timingFunction = linear
<CABasicAnimation:0x610000024220; toValue =
0.20000000298023224; removedOnCompletion = 0;
delegate = <UIViewAnimationState:
0x7fe69e0094e0>; fillMode = both; timingFunction
= linear; duration = 2; fromValue = 1; keyPath =
opacity>
1
opacity
64. 64
<CABasicAnimation:0x610000027340;
removedOnCompletion = 0; delegate =
<UIViewAnimationState: 0x7fe69e0094e0>; fillMode
= both; timingFunction = linear; duration = 2;
toValue = 100; fromValue = 0.0; keyPath =
uiFractionalProgress>
2
UIPacingAnimationForAnimatorsKey
uiFractionalProgress = 0 -> 100
duration = 2
timingFunction = linear
(lldb) po self.presentation()?.value(forKey:
"uiFractionalProgress")
▿ Optional<Any>
81. 81
let filepath = Bundle.main.path(forResource: "animation", ofType: "json")!
var contents = try! String(contentsOfFile: filepath)
contents = contents.replacingOccurrences(
of: "[0.6790901,0.178386,0.178386,1]",
with: “[0,0.9,0,1]"
)
contents = contents.replacingOccurrences(
of: "[0.6784314,0.1764706,0.1764706,1]",
with: “[0,0.9,0,1]"
)
let data = contents.data(using: .utf8)!
let json = try! JSONSerialization.jsonObject(
with: data,
options: []
) as? [String: Any]
animationView = LOTAnimationView(json: json)
82. 82
let filepath = Bundle.main.path(forResource: "animation", ofType: "json")!
var contents = try! String(contentsOfFile: filepath)
contents = contents.replacingOccurrences(
of: "[0.6790901,0.178386,0.178386,1]",
with: “[0,0.9,0,1]"
)
contents = contents.replacingOccurrences(
of: "[0.6784314,0.1764706,0.1764706,1]",
with: “[0,0.9,0,1]"
)
let data = contents.data(using: .utf8)!
let json = try! JSONSerialization.jsonObject(
with: data,
options: []
) as? [String: Any]
animationView = LOTAnimationView(json: json)
83. 83
let filepath = Bundle.main.path(forResource: "animation", ofType: "json")!
var contents = try! String(contentsOfFile: filepath)
contents = contents.replacingOccurrences(
of: "[0.6790901,0.178386,0.178386,1]",
with: “[0,0.9,0,1]"
)
contents = contents.replacingOccurrences(
of: "[0.6784314,0.1764706,0.1764706,1]",
with: “[0,0.9,0,1]"
)
let data = contents.data(using: .utf8)!
let json = try! JSONSerialization.jsonObject(
with: data,
options: []
) as? [String: Any]
animationView = LOTAnimationView(json: json)
Mutating Phase
84. 84
let filepath = Bundle.main.path(forResource: "animation", ofType: "json")!
var contents = try! String(contentsOfFile: filepath)
contents = contents.replacingOccurrences(
of: "[0.6790901,0.178386,0.178386,1]",
with: “[0,0.9,0,1]"
)
contents = contents.replacingOccurrences(
of: "[0.6784314,0.1764706,0.1764706,1]",
with: “[0,0.9,0,1]"
)
let data = contents.data(using: .utf8)!
let json = try! JSONSerialization.jsonObject(
with: data,
options: []
) as? [String: Any]
animationView = LOTAnimationView(json: json)
87. 87
• JSON
• Size (in both ways)
• Mutatablity
• Control
• Speed
• Progress
• Completion
• All AfterEffects magic
93. 93
• Avoid time-based animations 🚀
• Implement user interactions (it’s easy 😉)
• Create delegate for your custom
animations on VCs 🔊
• Check github.com/azimin/AZTransitions 👍