有人可以解释一下为什么我自己制作的符合 InsettableShape 的“myRectangle”不能与 .linesBorder 一起使用,但内置的 Rectangle() 可以吗?
这是 myRectangle 代码;
struct myRectangle: InsettableShape {
var insetAmount: CGFloat = 0
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.midX * 1.2, y: rect.maxY))
path.addLine(to: CGPoint(x: rect.midX * 1.2, y: rect.midY * 0.6))
path.addLine(to: CGPoint(x: rect.midX * 0.8, y: rect.midY * 0.6))
path.addLine(to: CGPoint(x: rect.midX * 0.8, y: rect.maxY))
return path
}
func inset(by amount: CGFloat) -> some InsettableShape {
var rectangle = self
rectangle.insetAmount -= amount
return rectangle
}
}
然后用 .linesBorder 修改它;
struct ColorCyclingRectangle: View {
var amount = 0.0
var steps = 100
var body: some View {
ZStack {
ForEach(0..<steps) { value in
myRectangle()
.inset(by: CGFloat(value))
.strokeBorder(self.color(for: value, brightness: 1), lineWidth: 2)
}
}
.drawingGroup()
}
func color(for value: Int, brightness: Double) -> Color {
var targetHue = Double(value) / Double(self.steps) + self.amount
if targetHue > 1 {
targetHue -= 1
}
return Color(hue: targetHue, saturation: 1, brightness: brightness)
}
}
我期待彩虹效果,但只是得到一条渐变线。
我尝试将路径修改为 - insetAmount 但我只是得到一个奇怪的形状,并且彩虹边框是直的,而不是方形的
我是否误解了什么,或者此修改器仅适用于默认形状?
虽然这是一个较旧的问题,但我会尝试回答它,希望OP仍然感兴趣或者它可以帮助其他人。
您绝对可以在符合 InsettableShape 协议的自定义类型上使用 strokeBorder() 修饰符,注意您有责任编写相应的插入(减小大小)自定义形状的代码。
我在代码中注意到的第一件事是,您在
path(in rect: CGRect)
方法中对某些值进行了硬编码,这就是为什么您的输出不是正方形的原因。两个选项是:
path(in rect: CGRect)
中使用它们来创建形状rect
的整个大小创建形状,并在要创建自定义形状的容器上或直接在形状上使用 .frame() 修饰符来控制其尺寸。我不确定哪个更好,但我将使用选项 2,因为这似乎是内置形状的工作方式 - 至少与宽度和高度相关 - 并且它使得更容易理解插入代码,如下所示
struct myRectangle: InsettableShape {
var insetAmount: CGFloat = 0
func path(in rect: CGRect) -> Path {
var path = Path()
path.move(to: CGPoint(x: rect.minX + insetAmount, y: rect.maxY - insetAmount))
path.addLine(to: CGPoint(x: rect.maxX - insetAmount, y: rect.maxY - insetAmount))
path.addLine(to: CGPoint(x: rect.maxX - insetAmount, y: rect.minY + insetAmount))
path.addLine(to: CGPoint(x: rect.minX + insetAmount, y: rect.minY + insetAmount))
path.addLine(to: CGPoint(x: rect.minX + insetAmount, y: rect.maxY - insetAmount))
return path
}
func inset(by amount: CGFloat) -> some InsettableShape {
var rectangle = self
rectangle.insetAmount += amount
return rectangle
}
}
在上面你会注意到:
rect
尺寸path(in rect: CGRect)
代码中使用了 insetAmount 变量。例如 path.move(to: CGPoint(x: rect.minX + insetAmount, y: rect.maxY - insetAmount))
是左下角。要插入这一点,您需要将 X 向右移动 rect.minX + insetAmount
,将 Y 向上移动 rect.maxY - insetAmount
- 我们从 Y 中减去以根据我的点 2 向上移动。在您的 ColorCyclingRectangle 自定义视图中,我仅向您要在其中创建自定义形状的 ZStack 容器添加了
.frame(width: 300, height: 300)
修饰符,以便我可以控制其大小。
struct ColorCyclingRectangle: View {
var amount = 0.0
var steps = 100
var body: some View {
ZStack {
ForEach(0..<steps) { value in
myRectangle()
.inset(by: CGFloat(value))
.strokeBorder(self.color(for: value, brightness: 1), lineWidth: 2)
}
}
.drawingGroup()
.frame(width: 300, height: 300)
}
func color(for value: Int, brightness: Double) -> Color {
var targetHue = Double(value) / Double(self.steps) + self.amount
if targetHue > 1 {
targetHue -= 1
}
return Color(hue: targetHue, saturation: 1, brightness: brightness)
}
}
这样我就能得到彩虹效果。
希望这能解决您的问题。