swiftui,如何制作卡套传播

问题描述 投票:0回答:1

我想把卡组摊开, 但是我就是炸也做不成那个形状。 需要帮助。

gpt 说用 sin cos 配合它,但我不熟悉 sin cos 和 swiftUI

        var body: some View {
        HStack(spacing: 10) {
            Spacer()
            ForEach(0..<10) { num in
                VStack {
                    GeometryReader { geo in
                        ZStack {
                            CardFront(width: width, height: height, num: num, degree: $frontDegrees[num])
                            CardBack(width: width, height: height, degree: $backDegrees[num])
                        }.onTapGesture {
                            flipCard(num)
                        }

                        // spread the cards based on the center
                        .offset(x: ((Double(num) + 0.6) * 90), y: 600).rotationEffect(.degrees(Double(num) * 6))
                    }
                }
                Spacer()
            }
            .navigationBarBackButtonHidden(true)
        }
    }
}
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        CardFlipView()

        CardFlipView()
            .previewInterfaceOrientation(.landscapeLeft)
    }
}

它应该是什么样子:

swift swiftui rotation effect card
1个回答
0
投票

我试图让一个例子起作用。点击卡片以切换扇形状态:

import SwiftUI

/// Encapsulates the layout logic for the cards
class Layout {

    /// The width available for showing the fanned cards
    let viewWidth: CGFloat

    /// The number of cards in the pack
    static let nCardsInPack = 10

    /// The width of a single card
    static let cardWidth = CGFloat(50)

    /// The height of a single card
    static let cardHeight = CGFloat(cardWidth * 1.4)

    /// The number of degrees for the arc of the spread.
    private static let arcDegrees = CGFloat(40)

    /// The number of radians for the arc of the spread.
    /// NB: 180 degrees = Pi radians
    private static let arcRadians = (arcDegrees * CGFloat.pi) / 180

    /// Creates the layout for showing the fanned cards, dependent on the supplied view width
    init(viewWidth: CGFloat) {
        self.viewWidth = viewWidth
    }

    /// - Returns the angle for the specified card when the pack is shown fanned
    func angleForCard(n: Int) -> CGFloat {
        let nGaps = max(CGFloat(Layout.nCardsInPack) - 1, 1)
        let fraction = (CGFloat(n) - (nGaps / 2)) / nGaps
        return fraction * Layout.arcRadians
    }

    /// - Returns the radius of the circle on which the fanned cards are
    /// spread out. Computed from the view width and arc for the spread
    private lazy var fanRadius: CGFloat = {
        let sinAngle = sin(Layout.arcRadians / 2.0)
        let availableWidth = (viewWidth - Layout.cardWidth) / 2.0
        return sinAngle == 0 ? availableWidth : availableWidth / sinAngle
    }()

    /// - Returns the x offset for card n, which may be negative
    func xOffsetForCard(n: Int) -> CGFloat {
        return sin(angleForCard(n: n)) * fanRadius
    }

    /// - Returns the y offset for card n
    func yOffsetForCard(n: Int) -> CGFloat {
        return fanRadius - (cos(angleForCard(n: n)) * fanRadius)
    }
}

/// View of an individual card
struct CardView: View {

    /// The index of this card in the pack, 0-based
    private let n: Int

    private let layout: Layout

    @Binding private var showSpreadOut: Bool

    init(n: Int, layout: Layout, showSpreadOut: Binding<Bool>) {
        self.n = n
        self.layout = layout
        self._showSpreadOut = showSpreadOut
    }

    private var angle: CGFloat {
        showSpreadOut ? layout.angleForCard(n: n) : 0
    }

    private var xOffset: CGFloat {
        showSpreadOut ? layout.xOffsetForCard(n: n) : 0
    }

    private var yOffset: CGFloat {
        showSpreadOut ? layout.yOffsetForCard(n: n) : 0
    }

    var body: some View {
        Text("\(n)")
            .font(.largeTitle)
            .foregroundColor(.white)
            .frame(width: Layout.cardWidth, height: Layout.cardHeight)
            .background(
                Color.blue
                    .opacity(0.2)
                    .cornerRadius(Layout.cardWidth / 10)
            )
            // Important: rotation must come before offsets!
            .rotationEffect(Angle(radians: angle))
            .offset(x: xOffset, y: yOffset)
            .animation(.easeInOut, value: showSpreadOut)
    }
}

/// View of a collection of cards
struct PackView: View {

    private let layout: Layout

    @Binding private var showSpreadOut: Bool

    init(layout: Layout, showSpreadOut: Binding<Bool>) {
        self.layout = layout
        self._showSpreadOut = showSpreadOut
    }

    var body: some View {
        ZStack() {
            ForEach(0..<Layout.nCardsInPack, id: \.self) { n in
                CardView(n: n, layout: layout, showSpreadOut: $showSpreadOut)
            }
        }
    }
}

struct ContentView: View {

    @State private var showSpreadOut = false

    var body: some View {
        GeometryReader { proxy in
            PackView(
                layout: Layout(viewWidth: proxy.size.width),
                showSpreadOut: $showSpreadOut
            )
            .onTapGesture { showSpreadOut.toggle() }
            .frame(width: proxy.size.width, height: proxy.size.height)
        }
    }
}

FannedCards

© www.soinside.com 2019 - 2024. All rights reserved.