我想為一張卡片制作影片,它從螢屏的上半部分飛到下半部分,并在飛行程序中翻轉。
.cardify我使用自定義修飾符控制翻轉邏輯。它似乎獨自作業,例如當我翻過一張卡片時onTapGesture { withAnimation { ... } }。
我還制作了一張卡片從螢屏頂部飛到底部,反之亦然matchedGeometryEffect。
但是,當我點擊卡片時,它會飛而不旋轉。
我試圖申請.transition(.assymetric(...))兩個 if 分支(見下面的代碼),但沒有幫助。
所以,代碼
import SwiftUI
struct ContentView: View {
@State var cardOnTop = true
@State var theCard = Card(isFaceUp: true)
@Namespace private var animationNameSpace
var body: some View {
VStack {
if cardOnTop {
CardView(card: theCard)
.matchedGeometryEffect(id: 1, in: animationNameSpace)
.onTapGesture {
withAnimation {
theCard.toggle()
cardOnTop.toggle() // comment me to test flipping alone
}
}
Color.white
} else {
Color.white
CardView(card: theCard)
.matchedGeometryEffect(id: 1, in: animationNameSpace)
.onTapGesture {
withAnimation {
theCard.toggle()
cardOnTop.toggle()
}
}
}
}
.padding()
}
struct Card {
var isFaceUp: Bool
mutating func toggle() {
isFaceUp.toggle()
}
}
struct CardView: View {
var card: Card
var body: some View {
Rectangle()
.frame(width: 100, height: 50)
.foregroundColor(.red)
.cardify(isFaceUp: card.isFaceUp)
}
}
}
/* Cardify ViewModifier */
struct Cardify: ViewModifier, Animatable {
init(isFaceUp: Bool){
rotation = isFaceUp ? 0 : 180
}
var rotation: Double // in degrees
var animatableData: Double {
get { return rotation }
set { rotation = newValue }
}
func body(content: Content) -> some View {
ZStack {
let shape = RoundedRectangle(cornerRadius: DrawingConstants.cornerRadius)
if rotation < 90 {
shape.fill().foregroundColor(.white)
shape.strokeBorder(lineWidth: DrawingConstants.lineWidth).foregroundColor(.gray)
} else {
shape.fill().foregroundColor(.gray)
}
content
.opacity(rotation < 90 ? 1 : 0)
}
.rotation3DEffect(Angle.degrees(rotation), axis: (0, 1, 0))
}
private struct DrawingConstants {
static let cornerRadius: CGFloat = 15
static let lineWidth: CGFloat = 2
}
}
extension View {
func cardify(isFaceUp: Bool) -> some View {
return self.modifier(Cardify(isFaceUp: isFaceUp))
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
我怎樣才能讓卡片旋轉飛行?
另外,我發現這行得通(如果單獨放在主體中VStack,則沒有 if 分支)
CardView(card: theCard)
.offset(x: 0, y: cardOnTop ? 0 : 100)
.onTapGesture {
withAnimation {
theCard.toggle()
cardOnTop.toggle() // comment me to test flipping alone
}
}
但在我的應用程式中,我有一副向下翻轉的卡片,這些卡片用于向上翻轉的棋盤。我試圖在ContentView上面的代碼中通過 if-branch 來模擬行為(CardViews 出現并消失)。
uj5u.com熱心網友回復:
這是一個純粹.transition使用自定義轉換的解決方案:

struct ContentView: View {
@State var cardOnTop = true
var body: some View {
VStack(spacing:0) {
if cardOnTop {
RoundedRectangle(cornerRadius: 15)
.fill(.blue)
.transition(.rotate3D(direction: 1).combined(with: .move(edge: .bottom)))
Color.clear
} else {
Color.clear
RoundedRectangle(cornerRadius: 15)
.fill(.green)
.transition(.rotate3D(direction: -1).combined(with: .move(edge: .top)))
}
}
.onTapGesture {
withAnimation(.easeInOut(duration: 2)) {
cardOnTop.toggle()
}
}
.padding()
}
}
/* Transition Modifier */
extension AnyTransition {
static func rotate3D(direction: Double) -> AnyTransition {
AnyTransition.modifier(
active: Rotate3DModifier(value: 1, direction: direction),
identity: Rotate3DModifier(value: 0, direction: direction))
}
}
struct Rotate3DModifier: ViewModifier {
let value: Double
let direction: Double
func body(content: Content) -> some View {
content
.rotation3DEffect(Angle(degrees: 180 * value * direction), axis: (x: 0, y: 1, z: 0))
.opacity(1 - value)
}
}
uj5u.com熱心網友回復:
不會觸發旋轉,因為您移除了卡片并將另一張卡片插入視圖中,所以只有.matchedGeometryEffect剩下的卡片。
你想要的是一張保持在視野中的卡片,這樣它就可以旋轉,但也可以改變它的位置。
您可以使用.offset. 這GeometryReader只是為了找到正確的偏移值。
var body: some View {
GeometryReader { geo in
VStack {
CardView(card: theCard)
.offset(x: 0, y: cardOnTop ? 0 : geo.size.height / 2)
.onTapGesture {
withAnimation {
cardOnTop.toggle()
theCard.toggle()
}
}
Color.clear
}
}
.padding()
}

轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/449628.html
