SwiftUI 自定义形状行为不符合预期
SwiftUI custom shape behavior not as expected
我正在关注 Stanford CS193P 2020 youtube 课程。我被自定义钻石形状的行为困住了。我的自定义形状框架(无论我放置哪个修饰符框架等)总是比绘制它的 space 大,内置形状总是采用给定的 space。这样做的结果是,根据 space 它的框架采用的尺寸,我所有的自定义形状都有不同的尺寸。我不知道如何解决这个问题。
具体的问题是,如何在我的自定义形状中获得与在矩形或胶囊中获得的相同的框架?
我将向您粘贴绘图的图像和下面的代码。谢谢你的帮助。
自定义形状代码。
import SwiftUI
struct Diamond:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
// get the center of the rect
let center = CGPoint(x: rect.midX, y: rect.midY)
// get the smallest between height and width
let minDimension = min(rect.width, rect.height)
// get the starting of our drawing the right side of our diamond
let startingPoint = CGPoint(x: center.x + minDimension / 2, y: center.y)
// move our start of drawing to the beggining point
path.move(to: startingPoint)
// distance / 2 is our height
// create all our points
let secondPoint = CGPoint(x: center.x, y: center.y + minDimension / 4)
let thirdPoint = CGPoint(x: center.x - minDimension / 2 , y: center.y)
let fourthPoint = CGPoint(x: center.x, y: center.y - minDimension / 4)
path.addLine(to: secondPoint)
path.addLine(to: thirdPoint)
path.addLine(to: fourthPoint)
path.addLine(to: startingPoint)
return path
}
}
形状绘图
import SwiftUI
struct SetCardView:View {
var card:SetGame<Figure,Shade,FigureColor>.Card
var body: some View {
switch card.figureType {
case .capsule:
return AnyView(GeometryReader { geometry in
VStack {
ForEach(0..<self.card.numberOfFiguresInCard) { _ in
Capsule(style: .circular)
.stroke(self.card.figureColor.createColor(), lineWidth: 4)
.frame(maxWidth: min(geometry.size.width, geometry.size.height), maxHeight: min(geometry.size.width,geometry.size.height) / 2 )
.overlay(
Capsule(style: .circular)
.fill(self.card.shadingType.createOpacity() != nil ? self.card.figureColor.createColor() : Color.white)
.opacity(self.card.shadingType.createOpacity() ?? 1))
.frame(idealWidth: geometry.size.width, idealHeight: geometry.size.width / 3 )
}
.frame(idealWidth: geometry.size.width)
.padding()
}.padding()
})
case .diamond:
return AnyView(GeometryReader { geometry in
VStack {
ForEach(0..<self.card.numberOfFiguresInCard) { _ in
VStack {
Diamond()
.stroke(self.card.figureColor.createColor(), lineWidth: 4)
.overlay(
Diamond()
.fill(self.card.shadingType.createOpacity() != nil ? self.card.figureColor.createColor() : Color.white)
.opacity(self.card.shadingType.createOpacity() ?? 1))
}
}.padding(.horizontal)
}
})
case .squiggle:
return AnyView(GeometryReader { geometry in
VStack {
ForEach(0..<self.card.numberOfFiguresInCard) { _ in
Rectangle()
.stroke(self.card.figureColor.createColor(), lineWidth: 4)
.frame(maxWidth: min(geometry.size.width, geometry.size.height), maxHeight: min(geometry.size.width,geometry.size.height) / 2 )
.overlay(
Rectangle()
.fill(self.card.shadingType.createOpacity() != nil ? self.card.figureColor.createColor() : Color.white)
.opacity(self.card.shadingType.createOpacity() ?? 1))
.frame(idealWidth: geometry.size.width)
}.padding()
}.padding()
})
}
}
}
struct SetCardView_Previews: PreviewProvider {
static var previews: some View {
let vm = FiguresSetGame()
return SetCardView(card:vm.cards.filter{[=11=].numberOfFiguresInCard == 2 && [=11=].figureType == .diamond}[1])
}
}
PD:我知道我可以通过将代码从函数中删除并使其不再重复来大大改进我的代码。
解决了我画错了我的钻石形状。
我不需要绘制整个框架,只需要绘制最小尺寸。那么菱形就会占据整个框架。
struct Diamond:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
// get the center of the rect
let center = CGPoint(x: rect.midX, y: rect.midY)
// get the starting of our drawing the right side of our diamond
let startingPoint = CGPoint(x: rect.maxX, y: center.y)
// move our start of drawing to the beggining point
path.move(to: startingPoint)
// distance / 2 is our height
// create all our points
let secondPoint = CGPoint(x: center.x, y: rect.maxY)
let thirdPoint = CGPoint(x: rect.minX , y: center.y)
let fourthPoint = CGPoint(x: center.x, y: rect.minY)
path.addLine(to: secondPoint)
path.addLine(to: thirdPoint)
path.addLine(to: fourthPoint)
path.addLine(to: startingPoint)
return path
}
}
我正在关注 Stanford CS193P 2020 youtube 课程。我被自定义钻石形状的行为困住了。我的自定义形状框架(无论我放置哪个修饰符框架等)总是比绘制它的 space 大,内置形状总是采用给定的 space。这样做的结果是,根据 space 它的框架采用的尺寸,我所有的自定义形状都有不同的尺寸。我不知道如何解决这个问题。 具体的问题是,如何在我的自定义形状中获得与在矩形或胶囊中获得的相同的框架? 我将向您粘贴绘图的图像和下面的代码。谢谢你的帮助。
自定义形状代码。
import SwiftUI
struct Diamond:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
// get the center of the rect
let center = CGPoint(x: rect.midX, y: rect.midY)
// get the smallest between height and width
let minDimension = min(rect.width, rect.height)
// get the starting of our drawing the right side of our diamond
let startingPoint = CGPoint(x: center.x + minDimension / 2, y: center.y)
// move our start of drawing to the beggining point
path.move(to: startingPoint)
// distance / 2 is our height
// create all our points
let secondPoint = CGPoint(x: center.x, y: center.y + minDimension / 4)
let thirdPoint = CGPoint(x: center.x - minDimension / 2 , y: center.y)
let fourthPoint = CGPoint(x: center.x, y: center.y - minDimension / 4)
path.addLine(to: secondPoint)
path.addLine(to: thirdPoint)
path.addLine(to: fourthPoint)
path.addLine(to: startingPoint)
return path
}
}
形状绘图
import SwiftUI
struct SetCardView:View {
var card:SetGame<Figure,Shade,FigureColor>.Card
var body: some View {
switch card.figureType {
case .capsule:
return AnyView(GeometryReader { geometry in
VStack {
ForEach(0..<self.card.numberOfFiguresInCard) { _ in
Capsule(style: .circular)
.stroke(self.card.figureColor.createColor(), lineWidth: 4)
.frame(maxWidth: min(geometry.size.width, geometry.size.height), maxHeight: min(geometry.size.width,geometry.size.height) / 2 )
.overlay(
Capsule(style: .circular)
.fill(self.card.shadingType.createOpacity() != nil ? self.card.figureColor.createColor() : Color.white)
.opacity(self.card.shadingType.createOpacity() ?? 1))
.frame(idealWidth: geometry.size.width, idealHeight: geometry.size.width / 3 )
}
.frame(idealWidth: geometry.size.width)
.padding()
}.padding()
})
case .diamond:
return AnyView(GeometryReader { geometry in
VStack {
ForEach(0..<self.card.numberOfFiguresInCard) { _ in
VStack {
Diamond()
.stroke(self.card.figureColor.createColor(), lineWidth: 4)
.overlay(
Diamond()
.fill(self.card.shadingType.createOpacity() != nil ? self.card.figureColor.createColor() : Color.white)
.opacity(self.card.shadingType.createOpacity() ?? 1))
}
}.padding(.horizontal)
}
})
case .squiggle:
return AnyView(GeometryReader { geometry in
VStack {
ForEach(0..<self.card.numberOfFiguresInCard) { _ in
Rectangle()
.stroke(self.card.figureColor.createColor(), lineWidth: 4)
.frame(maxWidth: min(geometry.size.width, geometry.size.height), maxHeight: min(geometry.size.width,geometry.size.height) / 2 )
.overlay(
Rectangle()
.fill(self.card.shadingType.createOpacity() != nil ? self.card.figureColor.createColor() : Color.white)
.opacity(self.card.shadingType.createOpacity() ?? 1))
.frame(idealWidth: geometry.size.width)
}.padding()
}.padding()
})
}
}
}
struct SetCardView_Previews: PreviewProvider {
static var previews: some View {
let vm = FiguresSetGame()
return SetCardView(card:vm.cards.filter{[=11=].numberOfFiguresInCard == 2 && [=11=].figureType == .diamond}[1])
}
}
PD:我知道我可以通过将代码从函数中删除并使其不再重复来大大改进我的代码。
解决了我画错了我的钻石形状。 我不需要绘制整个框架,只需要绘制最小尺寸。那么菱形就会占据整个框架。
struct Diamond:Shape {
func path(in rect: CGRect) -> Path {
var path = Path()
// get the center of the rect
let center = CGPoint(x: rect.midX, y: rect.midY)
// get the starting of our drawing the right side of our diamond
let startingPoint = CGPoint(x: rect.maxX, y: center.y)
// move our start of drawing to the beggining point
path.move(to: startingPoint)
// distance / 2 is our height
// create all our points
let secondPoint = CGPoint(x: center.x, y: rect.maxY)
let thirdPoint = CGPoint(x: rect.minX , y: center.y)
let fourthPoint = CGPoint(x: center.x, y: rect.minY)
path.addLine(to: secondPoint)
path.addLine(to: thirdPoint)
path.addLine(to: fourthPoint)
path.addLine(to: startingPoint)
return path
}
}