Swift:如何将点添加到封闭的CGPath?
我想让SKSpriteNodes沿着字母轮廓移动。 我有很多字母,但这里有一个例子:
我希望这个精灵跟着红线。 我发现这个答案主要涵盖了我的问题: 获取path在iOS UIFont中追踪一个字符
答案来自这个良好的工作示例代码:
let font = UIFont(name: "HelveticaNeue", size: 64)! var unichars = [UniChar]("P".utf16) var glyphs = [CGGlyph](count: unichars.count, repeatedValue: 0) let gotGlyphs = CTFontGetGlyphsForCharacters(font, &unichars, &glyphs, unichars.count) if gotGlyphs { let cgpath = CTFontCreatePathForGlyph(font, glyphs[0], nil)! let path = UIBezierPath(CGPath: cgpath) print(path) XCPlaygroundPage.currentPage.captureValue(path, withIdentifier: "glyph \(glyphs[0])") }
然而,我仍然遇到一个问题,因为我的精灵并没有完成所有字母的字母的完整path,而是例如在这里“P”停止(从底部开始):
我尝试添加一些点,如下所示:
CGPathAddLineToPoint(path, nil, 0, 0)
但结果不起作用可能是因为添加点在<Close>
语句之后:
<UIBezierPath: 0x7889ff70; <MoveTo {25.950001, 55.800003}>, <LineTo {25.950001, 95.100006}>, <LineTo {53.850002, 95.100006}>, <QuadCurveTo {71.625, 90.075005} - {66, 95.100006}>, <QuadCurveTo {77.25, 75.450005} - {77.25, 85.050003}>, <QuadCurveTo {71.625, 60.750004} - {77.25, 65.850006}>, <QuadCurveTo {53.850002, 55.800003} - {66, 55.650002}>, <Close>, <MoveTo {11.700001, 107.10001}>, <LineTo {11.700001, 0}>, <LineTo {25.950001, 0}>, <LineTo {25.950001, 43.800003}>, <LineTo {58.650002, 43.800003}>, <QuadCurveTo {83.175003, 52.050003} - {74.850006, 43.650002}>, <QuadCurveTo {91.5, 75.450005} - {91.5, 60.450001}>, <QuadCurveTo {83.175003, 98.775002} - {91.5, 90.450005}>, <QuadCurveTo {58.650002, 107.10001} - {74.850006, 107.10001}>, <Close>, <LineTo {0, 0}>
首先,你需要一个方法来检索CGPath
所有元素。
我已经翻译成Swift这种方法 (你也可以find一个如何使用它的例子)。
正如我在你的代码中看到的那样,你也需要知道什么types的元素组成了你的path,但是CGPathElement
和UnsafeMutablePointer<CGPoint>
CGPathElement
工作(它不能被UnsafeMutablePointer<CGPoint>
),所以你可以通过创build一个带有两个输出这样的数组:
//MARK: - CGPath extensions extension CGPath { func getPathElementsPointsAndTypes() -> ([CGPoint],[CGPathElementType]) { var arrayPoints : [CGPoint]! = [CGPoint]() var arrayTypes : [CGPathElementType]! = [CGPathElementType]() self.forEach { element in switch (element.type) { case CGPathElementType.MoveToPoint: arrayPoints.append(element.points[0]) arrayTypes.append(element.type) case .AddLineToPoint: arrayPoints.append(element.points[0]) arrayTypes.append(element.type) case .AddQuadCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) arrayTypes.append(element.type) arrayTypes.append(element.type) case .AddCurveToPoint: arrayPoints.append(element.points[0]) arrayPoints.append(element.points[1]) arrayPoints.append(element.points[2]) arrayTypes.append(element.type) arrayTypes.append(element.type) arrayTypes.append(element.type) default: break } } return (arrayPoints,arrayTypes) } }
之后,你有一个点arrays和一个reflectiontypes的数组,解释我们列表中的每个点是什么types。 这一次所有closePath
都被删除。
现在是时候为您重新创buildpath广告HOC了:
func createNewPath(path:CGPath) -> UIBezierPath { let (points,types) = path.getPathElementsPointsAndTypes() if points.count <= 1 { return UIBezierPath() // exit } let pathRef = UIBezierPath() var i = 0 while i < points.count { switch (types[i]) { case CGPathElementType.MoveToPoint: pathRef.moveToPoint(CGPointMake(points[i].x,points[i].y)) case .AddLineToPoint: pathRef.addLineToPoint(CGPointMake(points[i].x,points[i].y)) case .AddQuadCurveToPoint: pathRef.addQuadCurveToPoint(CGPointMake(points[i].x,points[i].y), controlPoint: CGPointMake(points[i+1].x,points[i+1].y)) i += 1 case .AddCurveToPoint: pathRef.addCurveToPoint(CGPointMake(points[i].x,points[i].y), controlPoint1: CGPointMake(points[i+1].x,points[i+1].y), controlPoint2: CGPointMake(points[i+2].x,points[i+2].y)) i += 2 default: break } i += 1 } //pathRef.closePath() if you want to add new elements dont uncomment this return pathRef }
启动这个方法之后,你将清除所有closePath
path,并随时添加新行。