2017-11-06 1 views
2

In meiner App brauche ich eine Kontur eines Pfeils, der mit Farbe gefüllt wird, wenn der Benutzer durch einige Aktivitäten fortschreitet. eine Pfeilform in meiner Ansicht erstellen ich UIView für den Einsatz im Interface Builder subclassed haben:Zeichnen Sie einen Rand um die pfeilförmige Maske

@IBDesignable 
class MaskedView: UIView { 

    var maskImageView = UIImageView() 

    @IBInspectable var maskImage: UIImage? { 
     didSet { 
      maskImageView.image = maskImage 
      maskImageView.contentMode = .scaleAspectFit 
      maskImageView.frame = bounds 
      mask = maskImageView 
     } 
    } 

} 

dann in IB ich wählen Sie ein Bild Pfeil, der die gewünschte Form erzeugt:

enter image description here

enter image description here

Hier hat die Ansicht einen grauen Hintergrund zu Demonstrationszwecken. Eigentlich muss ich es weiß sein mit Pfeil als schwarze Kontur mit:

enter image description here

Also im Grunde brauche ich einen Rahmen um meine Pfeil-Maske. Was ist der beste Weg, um dieses Ergebnis zu erreichen?

+0

Verwenden Sie UIBezierPath, um ein Pfadobjekt zu erstellen. –

+0

Lassen Sie mich wissen, wenn meine Antwort funktioniert? –

Antwort

1

yourView sollte in clearColor sein. Passen Sie CGPoint nach Ihrem Bedarf mit Hilfe von extension.

let arrow = UIBezierPath.arrow(from: CGPoint(x: 50, y: 100), to: CGPoint(x: 200, y: 50), 
             tailWidth: 10, headWidth: 25, headLength: 40) 
let caLay = CAShapeLayer() 
caLay.path = arrow.cgPath 
yourView.layer.mask = caLay 

let borderLayer = CAShapeLayer() 
borderLayer.path = arrow.cgPath // Reuse the Bezier path 
borderLayer.fillColor = UIColor.clear.cgColor 
borderLayer.strokeColor = UIColor.green.cgColor 
borderLayer.lineWidth = 5 
borderLayer.frame = greenview.bounds 
yourView.layer.addSublayer(borderLayer) 



extension UIBezierPath { 

    class func arrow(from start: CGPoint, to end: CGPoint, tailWidth: CGFloat, headWidth: CGFloat, headLength: CGFloat) -> Self { 
     let length = hypot(end.x - start.x, end.y - start.y) 
     let tailLength = length - headLength 

     func p(_ x: CGFloat, _ y: CGFloat) -> CGPoint { return CGPoint(x: x, y: y) } 
     var points: [CGPoint] = [ 
      p(0, tailWidth/2), 
      p(tailLength, tailWidth/2), 
      p(tailLength, headWidth/2), 
      p(length, 0), 
      p(tailLength, -headWidth/2), 
      p(tailLength, -tailWidth/2), 
      p(0, -tailWidth/2) 
     ] 

     let cosine = (end.x - start.x)/length 
     let sine = (end.y - start.y)/length 
     var transform = CGAffineTransform(a: cosine, b: sine, c: -sine, d: cosine, tx: start.x, ty: start.y) 
     let path = CGMutablePath() 
     path.addLines(between: points, transform: transform) 
     path.closeSubpath() 
     return self.init(cgPath: path) 
    } 

} 
+0

Ich dachte darüber nach, hoffte aber, das manuelle Zeichnen zu vermeiden, da es fehleranfällig und für AutoLayout schwer anzupassen war. Ich habe mich gefragt, ob es eine Möglichkeit gibt, UIBezierPath schnell aus der Bildform zu erstellen. Es erkennt die Form beim Erstellen einer Maske, also warum nicht einen Pfad um ihn mit gegebener Linienbreite zeichnen, dachte ich) –

+0

Außerdem besteht eine gute Chance, dass sich die Pfeilform in zukünftigen Versionen ändern wird. Es kann komplizierter werden, z.B. Nachahmung Federn auf dem Boden. Das erfordert 20-40 Punkte zu verwalten. –

Verwandte Themen