Please complete Chinese tutorial and see github.com/WillieWangW...
View animation and transitions
Use
SwiftUI
when, as a matter of where we can add animation for the view alone, or to view the status of animate.SwiftUI
For us to deal with all the combinations of animation, overlapping and interrupting complexity.In this article, we will animate the view that contains a chart to track users use
Landmarks
when behavior app. We'll see by using theanimation(_:)
animate method to view how simple yes.Download the project file and follow these steps, you can also open the completed project themselves through the code.
- Estimated Completion Time: 20 minutes
- Project File: Download
1. Single View to add animation
When we use on a view animation(_:)
when the method SwiftUI
dynamically modify this view can be animated properties. A view of the color, transparency, rotation, size, and other attributes are available animation.
1.1 HikeView.swift
, open the live preview to test the show and hide charts.
Ensure that the procedures in this article are open live preview, so you can test the results of each step.
1.2 Add animation(.basic())
method to open the rotation animation buttons.
HikeView.swift
import SwiftUI
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
self.showDetail.toggle()
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.padding()
.animation(.basic())
}
}
if showDetail {
HikeDetail(hike: hike)
}
}
}
}
复制代码
1.3 Add a button to make larger animation when the chart display.
animation(_:)
It will act in view of the packaging of all the animation changes.
HikeView.swift
import SwiftUI
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
self.showDetail.toggle()
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
.animation(.basic())
}
}
if showDetail {
HikeDetail(hike: hike)
}
}
}
}
复制代码
1.4 animation type from the .basic()
change .spring()
.
SwiftUI
Comprising with preset or custom easing basic animation, and an elastic and fluid animation. We can adjust the speed of the animation, set the delay before the animation begins, or specify the animation repeats.
HikeView.swift
import SwiftUI
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
self.showDetail.toggle()
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
.animation(.spring())
}
}
if showDetail {
HikeDetail(hike: hike)
}
}
}
}
复制代码
Try to scaleEffect
add another animation methods above method to close the rotation animation.
Around SwiftUI
try to combine different animation effects to see which effects are.
HikeView.swift
import SwiftUI
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
self.showDetail.toggle()
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.animation(nil)
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
.animation(.spring())
}
}
if showDetail {
HikeDetail(hike: hike)
}
}
}
}
复制代码
1.6 before proceeding with the next section, delete the two animation(_:)
methods.
HikeView.swift
import SwiftUI
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
self.showDetail.toggle()
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
}
}
if showDetail {
HikeDetail(hike: hike)
}
}
}
}
复制代码
2. The change of state of animation
Now if we have learned to add animation to a single view, it is time to change the status of the added value of the animation.
In this section, we will give the user clicks the button and switch showDetail
occurs when the state attribute all changes add animation.
2.1 showDetail.toggle()
calls package to withAnimation
function.
By the showDetail
open button and properties affect the HikeDetail
view now has an animated transitions.
HikeView.swift
import SwiftUI
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
withAnimation {
self.showDetail.toggle()
}
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
}
}
if showDetail {
HikeDetail(hike: hike)
}
}
}
}
复制代码
Slow down the animation to see SwiftUI
an animation of how you can interrupt.
To 2.2 withAnimation
The method of transmitting a base animation 4 seconds.
We can deliver the same type of animation to animation(_:)
the withAnimation
function.
HikeView.swift
import SwiftUI
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
withAnimation(.basic(duration: 4)) {
self.showDetail.toggle()
}
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
}
}
if showDetail {
HikeDetail(hike: hike)
}
}
}
}
复制代码
2.3 try to open and close the chart view during the animation.
2.4 Before entering the next section, from the withAnimation
removal of slow animation function.
HikeView.swift
import SwiftUI
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
withAnimation {
self.showDetail.toggle()
}
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
}
}
if showDetail {
HikeDetail(hike: hike)
}
}
}
}
复制代码
3. Customize View transitions
By default, view through the fade in and fade transition to the screen and the outer screen. We can use transition(_:)
methods to customize transitions.
3.1 is satisfied condition display to HikeView
add a transition(_:)
method.
Now slide the icon will appear and disappear.
HikeView.swift
import SwiftUI
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
withAnimation {
self.showDetail.toggle()
}
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
}
}
if showDetail {
HikeDetail(hike: hike)
.transition(.slide)
}
}
}
}
复制代码
3.2 The transition to extract AnyTransition
static properties.
This can keep the code clear when you expand a custom transition. For custom transition, we can use SwiftUI
the same .
reference numerals.
HikeView.swift
import SwiftUI
extension AnyTransition {
static var moveAndFade: AnyTransition {
AnyTransition.slide
}
}
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
withAnimation {
self.showDetail.toggle()
}
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
}
}
if showDetail {
HikeDetail(hike: hike)
.transition(.moveAndFade)
}
}
}
}
复制代码
3.3 replaced the use of move(edge:)
transitions, so the chart will slide in and out from the same side.
HikeView.swift
import SwiftUI
extension AnyTransition {
static var moveAndFade: AnyTransition {
AnyTransition.move(edge: .trailing)
}
}
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
withAnimation {
self.showDetail.toggle()
}
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
}
}
if showDetail {
HikeDetail(hike: hike)
.transition(.moveAndFade)
}
}
}
}
复制代码
3.4 using the asymmetric(insertion:removal:)
method to display to view and disappears provide different transitions.
HikeView.swift
import SwiftUI
extension AnyTransition {
static var moveAndFade: AnyTransition {
let insertion = AnyTransition.move(edge: .trailing)
.combined(with: .opacity)
let removal = AnyTransition.scale()
.combined(with: .opacity)
return .asymmetric(insertion: insertion, removal: removal)
}
}
struct HikeView: View {
var hike: Hike
@State private var showDetail = false
var body: some View {
VStack {
HStack {
HikeGraph(data: hike.observations, path: \.elevation)
.frame(width: 50, height: 30)
VStack(alignment: .leading) {
Text(hike.name)
.font(.headline)
Text(hike.distanceText)
}
Spacer()
Button(action: {
withAnimation {
self.showDetail.toggle()
}
}) {
Image(systemName: "chevron.right.circle")
.imageScale(.large)
.rotationEffect(.degrees(showDetail ? 90 : 0))
.scaleEffect(showDetail ? 1.5 : 1)
.padding()
}
}
if showDetail {
HikeDetail(hike: hike)
.transition(.moveAndFade)
}
}
}
}
复制代码
4. The combination of complex effects to animation
When you click the button below the strip, the graph switching between three different sets of data. In this section, we will use a combination of animation graphics composed of Capsule
dynamic, fluctuating transition.
4.1 showDetail
defaults changed true
, and the HikeView
preview is fixed canvas
, the
This allows us to still be able to see the chart in the context of the production of animation in other documents.
4.2 GraphCapsule.swift
, add a new computing animation attributes, and apply Capsule
the shape
.
GraphCapsule.swift
import SwiftUI
struct GraphCapsule: View {
var index: Int
var height: Length
var range: Range<Double>
var overallRange: Range<Double>
var heightRatio: Length {
max(Length(magnitude(of: range) / magnitude(of: overallRange)), 0.15)
}
var offsetRatio: Length {
Length((range.lowerBound - overallRange.lowerBound) / magnitude(of: overallRange))
}
var animation: Animation {
Animation.default
}
var body: some View {
Capsule()
.fill(Color.gray)
.frame(height: height * heightRatio, alignment: .bottom)
.offset(x: 0, y: height * -offsetRatio)
.animation(animation)
)
}
}
复制代码
4.3 The animation was changed elastic animation, using a bar graph so that the initial speed jump.
GraphCapsule.swift
import SwiftUI
struct GraphCapsule: View {
var index: Int
var height: Length
var range: Range<Double>
var overallRange: Range<Double>
var heightRatio: Length {
max(Length(magnitude(of: range) / magnitude(of: overallRange)), 0.15)
}
var offsetRatio: Length {
Length((range.lowerBound - overallRange.lowerBound) / magnitude(of: overallRange))
}
var animation: Animation {
Animation.spring(initialVelocity: 5)
}
var body: some View {
Capsule()
.fill(Color.gray)
.frame(height: height * heightRatio, alignment: .bottom)
.offset(x: 0, y: height * -offsetRatio)
.animation(animation)
)
}
}
复制代码
4.4 speed up the animation speed, shorten the time required to move to the new position of each section.
GraphCapsule.swift
import SwiftUI
struct GraphCapsule: View {
var index: Int
var height: Length
var range: Range<Double>
var overallRange: Range<Double>
var heightRatio: Length {
max(Length(magnitude(of: range) / magnitude(of: overallRange)), 0.15)
}
var offsetRatio: Length {
Length((range.lowerBound - overallRange.lowerBound) / magnitude(of: overallRange))
}
var animation: Animation {
Animation.spring(initialVelocity: 5)
.speed(2)
}
var body: some View {
Capsule()
.fill(Color.gray)
.frame(height: height * heightRatio, alignment: .bottom)
.offset(x: 0, y: height * -offsetRatio)
.animation(animation)
)
}
}
复制代码
4.5 The Capsule
position on the chart for each animation to add delay.
GraphCapsule.swift
import SwiftUI
struct GraphCapsule: View {
var index: Int
var height: Length
var range: Range<Double>
var overallRange: Range<Double>
var heightRatio: Length {
max(Length(magnitude(of: range) / magnitude(of: overallRange)), 0.15)
}
var offsetRatio: Length {
Length((range.lowerBound - overallRange.lowerBound) / magnitude(of: overallRange))
}
var animation: Animation {
Animation.spring(initialVelocity: 5)
.speed(2)
.delay(0.03 * Double(index))
}
var body: some View {
Capsule()
.fill(Color.gray)
.frame(height: height * heightRatio, alignment: .bottom)
.offset(x: 0, y: height * -offsetRatio)
.animation(animation)
)
}
}
复制代码
4.6 observe the custom animation between the chart when transition is how to create a ripple effect.
Reproduced in: https: //juejin.im/post/5cfbc5356fb9a07ee1691b10