我正在读取一个随机路径,并将其提取到其 Path.Element 组件中。然后,我尝试反转该过程并将提取的 Path.Element 组件连接在一起以创建最终路径。目前,我的代码部分工作正常;它绘制了路径的某些部分,但对于其他部分,它会在 Xcode 控制台中显示如下错误:
CGPathAddCurveToPoint:没有当前点。
CGPathCloseSubpath:没有当前点。
CGPathAddLineToPoint:没有当前点。
我不知道如何解决这个问题。在此过程中,我将路径分解成各个部分,并在不更改值的情况下尝试将所有部分重新组合在一起。但是,这些错误和问题不断出现。
import SwiftUI
struct ContentView: View {
@State private var myCustomPathComponents: [CustomPath] = pathComponents(path: comprehensivePath)
@State private var myPath: Path = Path()
var body: some View {
VStack {
GeometryReader { proxy in
Color.white
ForEach(myCustomPathComponents) { item in
item.pathValue
.stroke(.black, lineWidth: 2.0)
}
}
GeometryReader { proxy in
Color.white
ForEach(myCustomPathComponents) { item in
myFunc(value: item.pathElements)
.stroke(Color.red, lineWidth: 2.0)
}
}
}
.padding()
.onAppear {
print("count:", myCustomPathComponents.count)
print("- - - - - - - - - - -")
for item in myCustomPathComponents {
print(item.pathValue.cgPath)
print("- - - - - - - - - - -")
}
}
}
}
let comprehensivePath: Path = {
var path = Path()
// Line
path.move(to: CGPoint(x: 20, y: 20))
path.addLine(to: CGPoint(x: 120, y: 20))
// Circle
path.addEllipse(in: CGRect(x: 20, y: 30, width: 100, height: 100))
// Rectangle
path.addRect(CGRect(x: 150, y: 30, width: 100, height: 50))
// Quadratic Curve
path.move(to: CGPoint(x: 250, y: 20))
path.addQuadCurve(to: CGPoint(x: 300, y: 120), control: CGPoint(x: 275, y: 0))
// Cubic Curve
path.move(to: CGPoint(x: 20, y: 150))
path.addCurve(to: CGPoint(x: 120, y: 250), control1: CGPoint(x: 50, y: 100), control2: CGPoint(x: 90, y: 200))
// Polygon (Triangle)
path.move(to: CGPoint(x: 250, y: 150))
path.addLine(to: CGPoint(x: 300, y: 150))
path.addLine(to: CGPoint(x: 275, y: 200))
path.closeSubpath()
// Arc (part of a circle)
path.move(to: CGPoint(x: 150, y: 200))
path.addArc(center: CGPoint(x: 150, y: 200), radius: 50, startAngle: .degrees(0), endAngle: .degrees(180), clockwise: true)
return path
}()
struct CustomPath: Identifiable {
let id: UUID = UUID()
var pathValue: Path
var pathElements: [Path.Element]
}
func pathComponents(path: Path) -> [CustomPath] {
var components: [CustomPath] = []
var currentPath = Path()
var currentElements: [Path.Element] = []
path.forEach { element in
currentElements.append(element)
switch element {
case .move(to: let point):
// Save the current path as a `CustomPath` before starting a new one
if !currentPath.isEmpty {
components.append(CustomPath(pathValue: currentPath, pathElements: currentElements))
currentPath = Path()
currentElements = []
}
currentPath.move(to: point)
case .line(to: let point):
currentPath.addLine(to: point)
case .quadCurve(to: let endPoint, control: let controlPoint):
currentPath.addQuadCurve(to: endPoint, control: controlPoint)
case .curve(to: let endPoint, control1: let control1, control2: let control2):
currentPath.addCurve(to: endPoint, control1: control1, control2: control2)
case .closeSubpath:
currentPath.closeSubpath()
components.append(CustomPath(pathValue: currentPath, pathElements: currentElements))
currentPath = Path()
currentElements = []
}
}
// Append any remaining path if it hasn't been added yet
if !currentPath.isEmpty {
components.append(CustomPath(pathValue: currentPath, pathElements: currentElements))
}
return components
}
func myFunc(value: [Path.Element]) -> Path {
var finalPath = Path()
for element in value {
switch element {
case .move(to: let point):
finalPath.move(to: point)
case .line(to: let point):
finalPath.addLine(to: point)
case .quadCurve(to: let endPoint, control: let controlPoint):
finalPath.addQuadCurve(to: endPoint, control: controlPoint)
case .curve(to: let endPoint, control1: let control1, control2: let control2):
finalPath.addCurve(to: endPoint, control1: control1, control2: control2)
case .closeSubpath:
finalPath.closeSubpath()
}
}
return finalPath
}
这只是
pathComponents
功能中的一个简单错误。考虑一个包含元素 的路径
moveto, lineto, moveto, curveto, closepath
。将其传入的预期结果pathComponents
将导致前 2 个元素形成一个CustomPath
,后 3 个元素形成另一个 。但是,您的算法实际上将前 3 个元素分组为一个CustomPath
,将后 2 个元素分组为另一个 。尝试使用调试器逐步执行代码,并考虑当
forEach
到达第二个moveto
元素时会发生什么。在迭代开始时,currentElements
将包含前两个元素moveto
和lineto
。然后将第二个moveto
添加到currentElements
,使其成为[moveto, lineto, moveto]
。由于!currentPath.isEmpty
为真,您最终会创建一个 ,CustomPath
并将[moveto, lineto, moveto]
其作为pathElements
。下一次迭代将 acurveto
作为 的第一个元素currentElements
。当绘制第二个 时CustomPath
,您最终会调用addLine(to:)
而不调用move(to:)
,因此没有当前点。一个简单的解决方法是: