我有一个抽认卡活动,我从这里提取了一些代码来合并卡片翻转动画,因为这个级别的 swiftUI 有点超出我的工资等级。
但是,我还想在我的视图中添加“卡片”的幻灯片过渡。从左到屏幕中心或从右到屏幕中心,取决于用户是单击前进还是后退按钮。
这可能吗?
struct flashCardActivity: View {
@State var flashCardObj: flashCardObject
@State var flipped = false
@State var animate3d = false
@State var showButtonSet = false
@State var counter: Int = 0
var body: some View {
VStack {
progressBar(counter: self.$counter, totalCards: flashCardObj.words.count)
.padding(.top, 175)
.padding(.bottom, 80)
Spacer()
cardView(flipped: self.$flipped, animate3d: self.$animate3d, counter: self.$counter, flashCardObj: self.$flashCardObj)
rightWrongButtonSet().padding(.top, 20)
saveToMyListButton().padding(.top, 25)
nextPreviousButtonSet(fcO: self.$flashCardObj, counter: self.$counter).offset(y:50)
}.offset(y:-80)
}
}
struct cardView: View {
@Binding var flipped: Bool
@Binding var animate3d: Bool
@Binding var counter: Int
@Binding var flashCardObj: flashCardObject
var body: some View{
ZStack() {
flashCardItal(counter: $counter, fcO: $flashCardObj).opacity(flipped ? 0.0 : 1.0)
flashCardEng(counter: $counter, fcO: $flashCardObj).opacity(flipped ? 1.0 : 0.0)
}
.modifier(FlipEffect(flipped: $flipped, angle: animate3d ? 180 : 0, axis: (x: 1, y: 0)))
.onTapGesture {
withAnimation(Animation.linear(duration: 0.8)) {
self.animate3d.toggle()
}
}
}
}
struct FlipEffect: GeometryEffect {
var animatableData: Double {
get { angle }
set { angle = newValue }
}
@Binding var flipped: Bool
var angle: Double
let axis: (x: CGFloat, y: CGFloat)
func effectValue(size: CGSize) -> ProjectionTransform {
DispatchQueue.main.async {
self.flipped = self.angle >= 90 && self.angle < 270
}
let tweakedAngle = flipped ? -180 + angle : angle
let a = CGFloat(Angle(degrees: tweakedAngle).radians)
var transform3d = CATransform3DIdentity;
transform3d.m34 = -1/max(size.width, size.height)
transform3d = CATransform3DRotate(transform3d, a, axis.x, axis.y, 0)
transform3d = CATransform3DTranslate(transform3d, -size.width/2.0, -size.height/2.0, 0)
let affineTransform = ProjectionTransform(CGAffineTransform(translationX: size.width/2.0, y: size.height / 2.0))
return ProjectionTransform(transform3d).concatenating(affineTransform)
}
}
struct flashCardItal: View {
@Binding var counter: Int
@Binding var fcO: flashCardObject
var body: some View{
Text(fcO.words[counter].wordItal)
.font(Font.custom("Marker Felt", size: 40))
.foregroundColor(Color.black)
.frame(width: 325, height: 250)
.background(Color.teal)
.cornerRadius(20)
.shadow(radius: 10)
.padding(.bottom, 30)
.padding([.leading, .trailing], 10)
.zIndex(1)
}
}
struct flashCardEng: View {
@Binding var counter: Int
@Binding var fcO: flashCardObject
var body: some View{
VStack{
Text(fcO.words[counter].wordEng)
.font(Font.custom("Marker Felt", size: 40))
.foregroundColor(Color.black)
.padding(.bottom, 30)
.padding([.leading, .trailing], 10)
Text(fcO.words[counter].gender.rawValue)
.font(Font.custom("Marker Felt", size: 30))
.foregroundColor(Color.black)
.padding(.top, 2)
.padding([.leading, .trailing], 10)
} .frame(width: 325, height: 250)
.background(Color.teal)
.cornerRadius(20)
.shadow(radius: 10)
}
}
struct rightWrongButtonSet: View{
var body: some View{
HStack{
Button(action: {
}, label:
{Image("cancel")
.resizable()
.scaledToFit()
.frame(width: 65, height: 65)
}).padding(.leading, 80)
Spacer()
Button(action: {
}, label:
{Image("checked")
.resizable()
.scaledToFit()
.frame(width: 65, height: 65)
}).padding(.trailing, 80)
}
}
}
struct saveToMyListButton: View{
var body: some View{
Button(action: {}, label: {Text("Save to My List")})
}
}
struct nextPreviousButtonSet: View{
@Binding var fcO: flashCardObject
@Binding var counter: Int
var body: some View{
HStack{
Button(action: {
if counter > 0 {
counter = counter - 1
}
}, label:
{Image(systemName: "arrow.backward").resizable()
.bold()
.scaledToFit()
.frame(width: 65, height: 65)
.foregroundColor(Color.black)
}).padding(.leading, 90)
Spacer()
Button(action: {
if counter < fcO.words.count - 1 {
counter = counter + 1
}
}, label:
{Image(systemName: "arrow.forward").resizable()
.bold()
.scaledToFit()
.frame(width: 65, height: 65)
.foregroundColor(Color.black)
}).padding(.trailing, 90)
}
}
}
struct progressBar: View {
@Binding var counter: Int
let totalCards: Int
var body: some View {
VStack {
Text(String(counter) + "/" + String(totalCards)).offset(y:20)
ProgressView("", value: Double(counter), total: Double(totalCards))
.frame(width: 300).cornerRadius(10)
.scaleEffect(x: 1, y: 4)
}
}
}
struct flashCardActivity_Previews: PreviewProvider {
static var previews: some View {
flashCardActivity(flashCardObj: flashCardObject.Food)
}
}