Conflit SwiftUI avec animation rotation3DEffect
Nov 05 2020
code ref: https://github.com/amosgyamfi/swiftui-animation-library/blob/master/After%20WWDC2020/Parallax%203D/ios_3d_parallax.gif
Lorsque je change d'état horizontalAlignment et que je l'utilise dans VStack (alignement: horizontalAlignment), le contenu se déplace de gauche à centre.
Je veux basculer entre le centre et le début en appuyant sur le bouton
Effet actuel:
Attendez-vous à l'effet:
import SwiftUI
struct ContentView: View {
@State private var rotateIn3D = false
@State private var horizontalAlignment: HorizontalAlignment = .leading
let weatherBg = LinearGradient(gradient: Gradient(colors: [Color.blue, Color.white]), startPoint: .topLeading, endPoint: .bottomTrailing)
var body: some View {
VStack{
ZStack { // Weather
VStack(alignment: horizontalAlignment) {
Text("Wednesday")
Text("18°")
.font(.system(size: 44))
.fontWeight(.thin)
Spacer()
Image(systemName: "cloud.sun.fill")
Text("Partly Cloudy")
.frame(width: 150, height: 20, alignment: .leading)
Text("H:21° L:12°")
}
.padding()
.background(Color.blue)
.background(Color.yellow)
.cornerRadius(22)
.foregroundColor(.white)
}.frame(width: 170, height: 170, alignment: .leading)
.rotation3DEffect(.degrees(rotateIn3D ? 12 : -12), axis: (x: rotateIn3D ? 90 : -45, y: rotateIn3D ? -45 : -90, z: 0))
.animation(Animation.easeInOut(duration: 2).repeatForever(autoreverses: true))
.onAppear() {
rotateIn3D.toggle()
}
Button(action: {
horizontalAlignment = .center
}, label: {
Text("Change Horizontal Alignment to center")
})
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
.preferredColorScheme(/*@START_MENU_TOKEN@*/.dark/*@END_MENU_TOKEN@*/)
}
}
Réponses
2 Asperi Nov 05 2020 at 11:52
Faites simplement des animations par valeur de chaque état séparé.
Testé avec Xcode 12.1 / iOS 14.1
// ... other code
.rotation3DEffect(.degrees(rotateIn3D ? 12 : -12), axis: (x: rotateIn3D ? 90 : -45, y: rotateIn3D ? -45 : -90, z: 0))
.animation(Animation.easeInOut(duration: 2).repeatForever(autoreverses: true),
value: rotateIn3D) // << here !!
.animation(.default, value: horizontalAlignment) // << here !!
.onAppear() {
rotateIn3D.toggle()
}
1 Omid Nov 05 2020 at 09:52
Ici: comme vous le souhaitiez tout au centre
import SwiftUI
struct ContentView: View {
@State private var rotateIn3D = false
var body: some View {
VStack{
ZStack {
VStack {
Text("Wednesday")
Text("18°")
.font(.system(size: 44))
.fontWeight(.thin)
Spacer()
Image(systemName: "cloud.sun.fill")
Text("Partly Cloudy")
Text("H:21° L:12°")
}
.frame(width: 150, height: 150)
.padding()
.background(Color.blue)
.background(Color.yellow)
.cornerRadius(22)
.foregroundColor(.white)
}.frame(width: 170, height: 170, alignment: .leading)
.rotation3DEffect(.degrees(rotateIn3D ? 12 : -12), axis: (x: rotateIn3D ? 90 : -45, y: rotateIn3D ? -45 : -90, z: 0))
.animation(Animation.easeInOut(duration: 2).repeatForever(autoreverses: true))
.onAppear() {
rotateIn3D.toggle()
}
}
}
}
Mise à jour: version 2.0.0
import SwiftUI
struct ContentView: View {
@State var rotateIn3D = false
@State var alignmentToggle = false
let weatherBg = RadialGradient(gradient: Gradient(colors: [Color.blue, Color.white]), center: .center, startRadius: 30, endRadius: 200)
var body: some View {
ZStack
{
VStack(alignment: alignmentToggle ? .leading : .center)
{
Text("Wednesday")
Text("18°").font(.system(size: 44)).fontWeight(.thin)
Spacer()
Image(systemName: "cloud.sun.fill")
Text("Partly Cloudy")
Text("H:21° L:12°")
}
.padding()
.frame(width: 170, height: 170)
.background(weatherBg)
.foregroundColor(.white)
.cornerRadius(22)
.shadow(color: Color.black.opacity(0.7), radius: 10, x: 0, y: 30)
.rotation3DEffect(.degrees(rotateIn3D ? 12 : -12), axis: (x: rotateIn3D ? 90 : -45, y: rotateIn3D ? -45 : -90, z: 0))
.animation( rotateIn3D ? Animation.easeInOut(duration: 2).repeatForever(autoreverses: true) : Animation.easeInOut(duration: 2))
.onAppear() { rotateIn3D.toggle() }
VStack
{
Spacer()
Button("alignment toggle"){
rotateIn3D.toggle()
DispatchQueue.main.asyncAfter(deadline: .now() + 2.1) {
alignmentToggle.toggle()
DispatchQueue.main.asyncAfter(deadline: .now() + 2.1) {
rotateIn3D.toggle()
}
}
}
.font(.title)
.padding()
}
}
}
}