-
Notifications
You must be signed in to change notification settings - Fork 62
/
Copy pathDuoLoading.swift
119 lines (99 loc) · 4.3 KB
/
DuoLoading.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
//
// DuoLoading.swift
// PurposefulSwiftUIAnimations
// ANIMATION AND MEANING: Delight, Whimsy and brand style.
// System-provided loading indicators can sometimes feel out of context. So, create custom iOS (SwiftUI) loading animations to match your brand style and provide immersive UX like what Duolingo did for content loading
//
import SwiftUI
struct DuoLoading: View {
@State private var isBlinking = false
@State private var isWalking = false
@State private var isTilting = false
@State private var handMoving = false
@State private var isShouting = false
var body: some View {
VStack(spacing: 0) {
VStack {
MusicNotes()
.offset(x: 50)
ZStack {
// Body
Image("body")
HStack(spacing: 62) {
Image("rightHand")
.rotationEffect(.degrees(handMoving ? 25 : -15), anchor: .topTrailing)
Image("leftHand")
.rotationEffect(.degrees(handMoving ? 15 : -45), anchor: .topLeading)
}
// Face
VStack {
Image("face")
Image("mouth")
}
.offset(x: 6)
// Eyes, Nose and thoung
VStack(spacing: -12) {
// Eyes
HStack(spacing: 32) {
ZStack { // Left eye
Image("eyelid")
Image("pipul")
}
ZStack { // Right eye
Image("eyelid")
Image("pipul")
}
}
.scaleEffect(y: isBlinking ? 1 : 0)
.offset(x: 10)
// Nose, thoung
VStack(spacing: -8) {
Image("nose")
.zIndex(1)
Image("thoung")
.scaleEffect(x: isShouting ? 1.4 : 1)
.offset(y: isShouting ? -3: 4 )
}
.padding(.bottom)
.offset(x: 10)
}
}
.rotationEffect(.degrees(isTilting ? -30 : 3))
// Left and right hands
HStack(spacing: 32) {
Image("legRight")
.rotationEffect(.degrees(isWalking ? 0 : -25), anchor: .bottomLeading)
.offset(x: isWalking ? 0 : 60)
Image("legLeft")
.offset(x: isWalking ? 0 : -60)
.rotationEffect(.degrees(isWalking ? -25 : 0), anchor: .bottomLeading)
}
}
.onAppear {
withAnimation(.easeOut(duration: 0.2).delay(0.25).repeatCount(2)) {
isBlinking.toggle()
}
withAnimation(.easeInOut(duration: 0.2).delay(0.6).repeatForever(autoreverses: true)) {
isTilting.toggle()
}
withAnimation(.easeInOut(duration: 0.2).delay(0.6).repeatForever(autoreverses: true)) {
handMoving.toggle()
}
withAnimation(.easeInOut(duration: 0.2).delay(0.6).repeatForever(autoreverses: true)) {
isWalking.toggle()
}
withAnimation(.easeInOut(duration: 0.2).delay(0.6).repeatForever(autoreverses: true)) {
isShouting.toggle()
}
}
// Floor
Image("floor")
} // All views
}
}
struct DuoLoading_Previews: PreviewProvider {
static var previews: some View {
DuoLoading()
.preferredColorScheme(.dark)
}
}