How to Draw a Line in Swift 3

How to draw a line in Swift 3

To draw a line between two points the first thing you need is get the CGPoints from the current UIView, there are several ways of achieve this. I going to use an UITapGestureRecognizer for the sake of the sample to detect when you make a tap.

The another step is once you have the two points saved draw the line between the two points, and for this again you can use the graphics context as you try before or use CAShapeLayer.

So translating the explained above we get the following code:

class ViewController: UIViewController {

var tapGestureRecognizer: UITapGestureRecognizer!

var firstPoint: CGPoint?
var secondPoint: CGPoint?

override func viewDidLoad() {
super.viewDidLoad()

tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(self.showMoreActions(touch:)))
tapGestureRecognizer.numberOfTapsRequired = 1
view.addGestureRecognizer(tapGestureRecognizer)
}

func showMoreActions(touch: UITapGestureRecognizer) {
let touchPoint = touch.location(in: self.view)

guard let _ = firstPoint else {
firstPoint = touchPoint
return
}

guard let _ = secondPoint else {
secondPoint = touchPoint
addLine(fromPoint: firstPoint!, toPoint: secondPoint!)

firstPoint = nil
secondPoint = nil

return
}
}

func addLine(fromPoint start: CGPoint, toPoint end:CGPoint) {
let line = CAShapeLayer()
let linePath = UIBezierPath()
linePath.move(to: start)
linePath.addLine(to: end)
line.path = linePath.cgPath
line.strokeColor = UIColor.red.cgColor
line.lineWidth = 1
line.lineJoin = kCALineJoinRound
self.view.layer.addSublayer(line)
}
}

The above code is going to draw a line every time two points are selected and you can customize the above function as you like.

I hope this help you.

Drawing a line in Swift 3.x with UIBezierPath

I use this to draw a line:

    let doYourPath = UIBezierPath(rect: CGRect(x: xPos, y: yPos, width: yourWidth, height: yourHeight))
let layer = CAShapeLayer()
layer.path = doYourPath.cgPath
layer.strokeColor = UIColor.white.cgColor
layer.fillColor = UIColor.white.cgColor

self.view.layer.addSublayer(layer)

Hope this help you out. This is just one the way to draw a line in swift.

draw a straight line in swift 3 and core graphics

You need keep the current context until the line draw process has ended, after that you need keep the current image and clear the context, draw the saved image again, and draw the new line. When the touch ended is called clean the current context and save the current image, after that start the new line draw process again

this is the full code

import UIKit

class ViewController2: UIViewController {

@IBOutlet weak var drawingPlace: UIImageView!

var startTouch : CGPoint?
var secondTouch : CGPoint?
var currentContext : CGContext?
var prevImage : UIImage?

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
startTouch = touch?.location(in: drawingPlace)
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
secondTouch = touch.location(in: drawingPlace)

if(self.currentContext == nil)
{
UIGraphicsBeginImageContext(drawingPlace.frame.size)
self.currentContext = UIGraphicsGetCurrentContext()
}else{
self.currentContext?.clear(CGRect(x: 0, y: 0, width: drawingPlace.frame.width, height: drawingPlace.frame.height))
}

self.prevImage?.draw(in: self.drawingPlace.bounds)

let bezier = UIBezierPath()

bezier.move(to: startTouch!)
bezier.addLine(to: secondTouch!)
bezier.close()

UIColor.blue.set()

self.currentContext?.setLineWidth(4)
self.currentContext?.addPath(bezier.cgPath)
self.currentContext?.strokePath()
let img2 = self.currentContext?.makeImage()
drawingPlace.image = UIImage.init(cgImage: img2!)
}
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

self.currentContext = nil
self.prevImage = self.drawingPlace.image
}
}

results

Sample Image

How to draw a line between two views in Swift 3?

I now solved my problem (more or less) as following:

class Line: NSView{
var fromPoint = CGPoint()
var toPoint = CGPoint()

func setPoints(fromPoint: CGPoint, toPoint: CGPoint){
self.fromPoint = fromPoint
self.toPoint = toPoint
}

override func draw(_ dirtyRect: NSRect) {
let path = NSBezierPath()

NSColor.green.setFill()
path.move(to: fromPoint)
path.line(to: toPoint)
path.stroke()
}
}

class ViewController: NSViewController{
override function viewDidLoad(){
super.viewDidLoad()

let subview3 = Line(frame: self.view.bounds)
subview3.setPoints(fromPoint: subview1.convert(CGPoint(x: subview1.bounds.maxX, y: subview1.bounds.maxY), to: self.view), toPoint: subview2.convert(CGPoint(x: subview2.bounds.minX, y: subview2.bounds.minY), to: self.view))
self.view.addSubview(subview3)
}
}

I need to know how to do this on runtime. Do I always have to create a new view in order to draw a path?

A full example:

//
// ViewController.swift
// DrawConnectViews
//
// Created by T M on 17.06.17.
// Copyright © 2017 TM. All rights reserved.
//

import Cocoa

class ViewController: NSViewController {

override func viewDidLoad() {
super.viewDidLoad()

let subview1 = CustomViewWithColor(frame: NSRect(origin: CGPoint(x: 10.0, y: 10.0), size: CGSize(width: 200.0, height: 200.0)))
let subview2 = CustomViewWithColor(frame: NSRect(origin: CGPoint(x: 360.0, y: 360.0), size: CGSize(width: 200.0, height: 200.0)))

// create a subview programatically:
let subview3 = Line(frame: self.view.bounds)
subview3.setPoints(fromPoint: subview1.convert(CGPoint(x: subview1.bounds.maxX, y: subview1.bounds.maxY), to: self.view), toPoint: subview2.convert(CGPoint(x: subview2.bounds.minX, y: subview2.bounds.minY), to: self.view))
self.view.addSubview(subview3)

subview1.setColor(color: NSColor.red)
subview2.setColor(color: NSColor.blue)
self.view.addSubview(subview1)
self.view.addSubview(subview2)
}

override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}

}

class CustomViewWithColor: NSView{
var color = NSColor()

func setColor(color: NSColor){
self.color = color
}

override func draw(_ dirtyRect: NSRect) {
let path = NSBezierPath(rect: self.bounds)
self.color.setFill()
path.fill()

}
}

class Line: NSView{
var fromPoint = CGPoint()
var toPoint = CGPoint()

func setPoints(fromPoint: CGPoint, toPoint: CGPoint){
self.fromPoint = fromPoint
self.toPoint = toPoint
}

override func draw(_ dirtyRect: NSRect) {
let path = NSBezierPath()

NSColor.green.setFill()
path.move(to: fromPoint)
path.line(to: toPoint)
path.stroke()
}
}

That produces following:
Output of program

How to draw a line in the simplest way in swift

Try looking into UIBezierPath, it will help you a lot for drawing lines. Here is documentation. Here is an example:

override func drawRect(rect: CGRect) {
let aPath = UIBezierPath()

aPath.move(to: CGPoint(x:<#start x#>, y:<#start y#>))
aPath.addLine(to: CGPoint(x: <#end x#>, y: <#end y#>))

// Keep using the method addLine until you get to the one where about to close the path
aPath.close()

// If you want to stroke it with a red color
UIColor.red.set()
aPath.lineWidth = <#line width#>
aPath.stroke()
}

Make sure you put this code in the drawRect, like in the example above.

If you need to update the drawing just call setNeedsDisplay() to update.

Draw a line realtime with Swift 3.0

You have to begin the image context:

UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0)

You also have to stroke the path:

context?.strokePath()

You also are not drawing the previous image:

imageView.image?.draw(in: view.bounds)

Thus:

func drawLine(from fromPoint: CGPoint, to toPoint: CGPoint) {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0)

imageView.image?.draw(in: view.bounds)

let context = UIGraphicsGetCurrentContext()

context?.move(to: fromPoint)
context?.addLine(to: toPoint)

context?.setLineCap(CGLineCap.round)
context?.setLineWidth(brushWidth)
context?.setStrokeColor(red: red, green: green, blue: blue, alpha: 1.0)
context?.setBlendMode(CGBlendMode.normal)
context?.strokePath()

imageView.image = UIGraphicsGetImageFromCurrentImageContext()
imageView.alpha = opacity
UIGraphicsEndImageContext()
}

How to draw line between two views in Swift

You have a couple of choices.

You can create a custom subclass of UIView that implements the draw(_:) function to draw custom content. That view would need to big enough to enclose all of your custom drawing. You'd fill most of the view with clear, and then draw the lines you want using Core Graphics.

The other option is to use Core Animation layers. You could add a CAShapeLayer to your view's layer, set up the shape layer with the desired line thickness and color, and add a path to the layer containing the lines you want to draw. (Note that if you use CAShapeLayers, all the lines drawn in a single shape layer will be the same color. You'll need multiple shape layers in order to draw in multiple colors.)

Both approaches will require some research. Shape layers are more efficient and take better advantage of the graphics hardware on iOS devices, but using them has a fairly steep learning curve.

You should be able to google examples of both approaches. Try search phrases like "Custom drawing in a UIView" and "drawing with CAShapeLayer". I wrote a little demo app called OvalView that demonstrates how to create a UIView subclass that manages a shape layer.

Edit:

I adapted the code from my sample app into a demo called LinesBetweenViews. The new demo has a custom UIView that draws lines between any pairs of subviews you put into it.

Here is a screenshot of the demo:

Sample Image

If you answer my questions I can upload the demo app to Github so you can look at it.

Edit #2

See this Github repo for a sample project that draws lines between pairs of subviews.



Related Topics



Leave a reply



Submit