2016-05-07 13 views
2

Ich möchte SKSpriteNodes entlang von Buchstabenkonturen verschieben lassen. Ich habe viele Briefe, aber hier ist ein Beispiel:Swift: Wie füge ich Punkte zu einem geschlossenen CGPath hinzu?

enter image description here

Ich würde das Sprite wie die rote Linie zu folgen. Ich fand diese Antwort, die meistens mein Problem behandelt: Get path to trace out a character in an iOS UIFont

Die Antwort kommt mit diesem guten und Arbeitsbeispielcode:

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])") 
} 

Jedoch habe ich nach wie vor ein Problem wie mein Sprite läuft nicht vollständigen Pfad vervollständigen um der Buchstabe für alle Buchstaben aber stattdessen zB mit „P“ stoppt hier (und begann von unten):

enter image description here

Ich habe versucht, ein paar Punkte auf den path wie so hinzufügen:

CGPathAddLineToPoint(path, nil, 0, 0) 

aber das Ergebnis nicht funktioniert wahrscheinlich, weil der Mehrpunkt ist nach der <Close> Aussage:

<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}> 

Antwort

2

allererst Sie eine Methode müssen alle Elemente ausabrufen.

Ich habe übersetzt in Swift diese method (Sie finden auch ein Beispiel, wie man es benutzt).

Wie ich hier im Code sehen können, müssen Sie auch wissen, welche Art von Element Ihren Weg komponieren, aber CGPathElement Arbeit mit UnsafeMutablePointer<CGPoint> (kann es nicht komfortabel sein), so dass Sie meine Übersetzung durch die Schaffung einer Funktion ändern können, mit zwei Ausgangsanordnungen wie folgt aus:

//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) 
    } 
} 

Danach haben Sie eine Reihe von Punkten und eine spiegelnde Array vom Typ, die erklären, welche Art jeder Punkt in unserer Liste ist. Diesmal sind alle closePath entfernt.

Jetzt ist es Zeit, Weg ad hoc für Sie Situation neu zu erstellen:

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 
    } 

Nach dieser Methode starten, werden Sie Ihren Weg durch alle closePath und fertig gereinigt haben neue Zeilen hinzufügen, wie Sie es wünschen.