Add two paths together using UIBezierPath in Swift - ios

I have 2 lines drawn using UIBezierPath, how can i combine point to form a shape inform of letter X. I want to join both lines together
Path 1
let path1 = UIBezierPath()
path1.move(to: .zero)
path1.addLine(to: CGPoint(x: 100, y: 100))
path1.close()
path1.lineWidth = 1.0
UIColor.blue.set()
path1.stroke()
path1.fill()
Path 2
let path2 = UIBezierPath()
path2.move(to: .zero)
path2.addLine(to: CGPoint(x: 50, y: 50))
path2.close()
path2.lineWidth = 1.0
UIColor.red.set()
path2.stroke()
path2.fill()

You should use proper CGPoint values
If your view bounds value is (0,0,100,100)
Move to (0,0)
Addline to (100,100)
Mode to (0,100)
Addline to (100,0)
Try this
let path = UIBezierPath()
path.move(to: .zero)
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.maxY))
path.move(to: CGPoint(x: bounds.minX, y: bounds.maxY))
path.addLine(to: CGPoint(x: bounds.maxX, y: bounds.minY))
path.close()
path.lineWidth = 1.0
UIColor.blue.set()
path.stroke()
path.fill()

Related

Add curve on arc swift

I want to generate a curve in the middle of a line programatically, however the edge of the curve is not rounded using my current solution.
func createPath() -> CGPath {
let height: CGFloat = 86.0
let path = UIBezierPath()
let centerWidth = self.frame.width / 2
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: (centerWidth - (height/2)), y: 0))
path.addArc(withCenter: CGPoint(x: centerWidth, y: 0), radius: 80 / 2, startAngle: 180 * CGFloat(PI)/180, endAngle: 0 * CGFloat(PI)/180, clockwise: false)
path.addLine(to: CGPoint(x: self.frame.width, y: 0))
path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height))
path.addLine(to: CGPoint(x: 0, y: self.frame.height))
path.lineCapStyle = .round
path.stroke()
path.close()
self.path = path
return path.cgPath
}
This is the Arc I have created but I want the curves to be rounded:
But I want it to be like this:
This is the code that you need
func createPath() -> CGPath {
let padding: CGFloat = 5.0
let centerButtonHeight: CGFloat = 53.0
let f = CGFloat(centerButtonHeight / 2.0) + padding
let h = frame.height
let w = frame.width
let halfW = frame.width/2.0
let r = CGFloat(18)
let path = UIBezierPath()
path.move(to: .zero)
path.addLine(to: CGPoint(x: halfW-f-(r/2.0), y: 0))
path.addQuadCurve(to: CGPoint(x: halfW-f, y: (r/2.0)), controlPoint: CGPoint(x: halfW-f, y: 0))
path.addArc(withCenter: CGPoint(x: halfW, y: (r/2.0)), radius: f, startAngle: .pi, endAngle: 0, clockwise: false)
path.addQuadCurve(to: CGPoint(x: halfW+f+(r/2.0), y: 0), controlPoint: CGPoint(x: halfW+f, y: 0))
path.addLine(to: CGPoint(x: w, y: 0))
path.addLine(to: CGPoint(x: w, y: h))
path.addLine(to: CGPoint(x: 0.0, y: h))
path.close()
return path.cgPath
}
Result:
You can customize the size of the button...
For a great explanation of how it is work, I recommend you to read this explanation, and you can draw any shape which do you want: https://ayusinghi96.medium.com/draw-custom-shapes-and-views-with-uiberzierpath-ios-1737f5cb975
You can just draw more arc like you already does. Or may be you can use path.addCurve, if you dont want oval
func createPath() -> CGPath {
let bigRadius: CGFloat = 40.0
let path = UIBezierPath()
let centerWidth = self.frame.width / 2
path.move(to: CGPoint(x: 0, y: 0))
let radius: CGFloat = 4 //change it if you want
let leftArcOriginX = centerWidth - bigRadius - radius
let leftArcOriginY: CGFloat = 0
path.addLine(to: CGPoint(x: leftArcOriginX, y: leftArcOriginY))
// add left little arc, change angle if you want, if you dont want oval, may be you can use path.addCurve(to: , controlPoint1: , controlPoint2: )
path.addArc(withCenter: CGPoint(x: leftArcOriginX, y: leftArcOriginY + radius), radius: radius, startAngle: CGFloat(270.0 * Double.pi/180.0), endAngle: 0, clockwise: true)
// add big arc
path.addArc(withCenter: CGPoint(x: centerWidth, y: radius), radius: bigRadius, startAngle: CGFloat(180.0 * Double.pi/180.0), endAngle: CGFloat(0 * Double.pi/180.0), clockwise: false)
// add right litte arc
path.addArc(withCenter: CGPoint(x: centerWidth + bigRadius + radius, y: radius), radius: radius, startAngle: CGFloat(180.0 * Double.pi/180.0), endAngle: CGFloat(270.0 * Double.pi/180.0), clockwise: true)
path.addLine(to: CGPoint(x: self.frame.width, y: 0))
path.addLine(to: CGPoint(x: self.frame.width, y: self.frame.height))
path.addLine(to: CGPoint(x: 0, y: self.frame.height))
path.lineCapStyle = .round
path.stroke()
path.close()
return path.cgPath
}

How to create dotted step indicator in swift 5(iOS)

I have a requirement like to draw a dotted step indicator in swift 5. I have searched for lot of tutorials on the same but I couldn't get the proper result. I need the step indicator which should be in vertical position(Top to Bottom). I have used the following code but it is coming wrongly when I run the app in iPad.
private func drawLinePath() {
//let linePath = UIBezierPath()
let path = UIBezierPath()
let centerX = self.frame.width / 2.0
let lineHeight = self.frame.height / 10
path.move(to: CGPoint(x: centerX, y: 0))
path.addLine(to: CGPoint(x: centerX, y: lineHeight))
path.move(to: CGPoint(x: centerX, y:lineHeight + 3))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 5))
path.move(to: CGPoint(x: centerX, y:lineHeight + 8))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 10))
path.move(to: CGPoint(x: centerX, y:lineHeight + 12))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 15))
path.move(to: CGPoint(x: centerX, y:lineHeight + 18))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 21 ))
path.move(to: CGPoint(x: centerX, y:lineHeight + 23))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 26))
path.move(to: CGPoint(x: centerX, y:lineHeight + 28))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 31))
path.move(to: CGPoint(x: centerX, y:lineHeight + 33))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 36))
path.move(to: CGPoint(x: centerX, y:lineHeight + 38))
path.addLine(to: CGPoint(x: centerX, y: lineHeight + 41))
self.path = path.cgPath
}
here is code working perfectly.
func drawLineFromPoint(start : CGPoint, toPoint end:CGPoint, ofColor lineColor: UIColor, inView view:UIView) {
//design the path
let path = UIBezierPath()
path.move(to: start)
path.addLine(to: end)
//design path in layer
let shapeLayer = CAShapeLayer()
shapeLayer.path = path.cgPath
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = lineColor.cgColor
shapeLayer.lineWidth = 4.0
shapeLayer.lineCap = .round
shapeLayer.lineDashPattern = [0.001,16]
shapeLayer.lineDashPhase = 4
view.layer.addSublayer(shapeLayer)
}
func drawLine() {
let frm1: CGRect = img1.frame
let frm2 : CGRect = img2.frame
drawLineFromPoint(start: CGPoint(x: frm1.origin.x + 12, y: frm1.origin.y + 25), toPoint: CGPoint(x: frm1.origin.x + 12, y: frm2.origin.y), ofColor: UIColor.black, inView: self.view)
}
override func viewDidLoad() {
super.viewDidLoad()
drawLine()
}
here is image
For that dotted path you can take UILabel and set text as '......' with your required font size and color. No need to draw any Bezier path. Just use UILabel.
take UIView for dashed line and use below code for line.
extension UIView {
func createDashedLine(from point1: CGPoint, to point2: CGPoint, color: UIColor, strokeLength: NSNumber, gapLength: NSNumber, width: CGFloat) {
let shapeLayer = CAShapeLayer()
shapeLayer.strokeColor = color.cgColor
shapeLayer.lineWidth = width
shapeLayer.lineDashPattern = [strokeLength, gapLength]
let path = CGMutablePath()
path.addLines(between: [point1, point2])
shapeLayer.path = path
layer.addSublayer(shapeLayer)
}}
Now use it like below..
let topPoint = CGPoint(x: vw.frame.midX, y: vw.bounds.minY)
let bottomPoint = CGPoint(x: vw.frame.midX, y: vw.bounds.maxY)
vw.createDashedLine(from: topPoint, to: bottomPoint, color: .lightGray, strokeLength: 4, gapLength: 6, width: 2)
You can use StepIndicator pod for that, you can find example from this link
https://github.com/chenyun122/StepIndicator
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: CGSize.init(width: 20, height: 40))
let layer = CAShapeLayer()
let path = UIBezierPath(roundedRect: rect, cornerRadius: 4)
layer.path = path.cgPath
layer.strokeColor = UIColor.gray.cgColor
layer.lineDashPattern = [3,3];
layer.backgroundColor = _CLEAR_COLOR.cgColor;
layer.fillColor = _CLEAR_COLOR.cgColor;
viewDottedLine.layer.addSublayer(layer);
Change rect values as per your view and lineDashPattern.
Hope that will work for you.

How to set the color for shape in cgmutablepath?

I am using cgmutablepath to draw a polygon where i would like to fill color for the polygon but it is not working and i have no idea why...
Below is my code:
var path = CGMutablePath()
path.move(to: CGPoint(x: 127.5, y: 12.5))
path.addLine(to: CGPoint(x: 165.0, y: 13.0))
path.addLine(to: CGPoint(x: 165.0, y: 50.5))
path.addLine(to: CGPoint(x: 127.5, y: 50.5))
path.closeSubpath()
var shape = CAShapeLayer()
shape.path = path
shape.lineWidth = 3.0
shape.strokeColor = UIColor.blue.cgColor
shape.fillColor = UIColor.blue.cgColor
Try replacing your code with this updated code :
var path = CGMutablePath()
path.move(to: CGPoint(x: 127.5, y: 12.5))
path.addLine(to: CGPoint(x: 165.0, y: 13.0))
path.addLine(to: CGPoint(x: 165.0, y: 50.5))
path.addLine(to: CGPoint(x: 127.5, y: 50.5))
path.closeSubpath()
var shape = CAShapeLayer()
shape.path = path
shape.lineWidth = 3.0
shape.strokeColor = UIColor.blue.cgColor
shape.fillColor = UIColor.blue.cgColor
self.layer.addSublayer(shapeLayer)
Please try it out and comment in case of any error. Happy Coding.

How to add multiple bezier paths into same view swift 3

I have added a triangle in this way
// draw the line graph
UIColor.white.setFill()
UIColor.white.setStroke()
///--------SETUP FIRST TRIANGLE-----------------------------------------------
//set up the points line
let graphPath = UIBezierPath()
//go to start of line
graphPath.move(to: CGPoint.init(x: rect.minX, y: rect.minY))
graphPath.addLine(to: CGPoint.init(x: (rect.maxX/2.0), y: (rect.maxY/2.0)))
graphPath.addLine(to: CGPoint.init(x: rect.minX, y: rect.maxY))
graphPath.stroke()
//2 - make a copy of the path
let clippingPath = graphPath.copy() as! UIBezierPath
//3 - add lines to the copied path to complete the clip area
clippingPath.addLine(to: CGPoint.init(x: rect.minX, y: rect.minY))
clippingPath.close()
//4 - add the clipping path to the context
clippingPath.addClip()
let startPoint = CGPoint(x:(rect.maxX/2.0), y: (rect.maxY/2.0))
let endPoint = CGPoint(x:rect.minX, y:(rect.maxY/2.0))
let gradient=self.getGradient(tiangleNo: 1)
let context = UIGraphicsGetCurrentContext()
context!.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: CGGradientDrawingOptions(rawValue: 0))
This is drawing a triangle that I wanted. Now I want to draw another triangle. So I did like this.
///------------SECOND TRIANGLE -----------------------------------------------
let graphPath2 = UIBezierPath()
graphPath2.move(to: CGPoint.init(x: rect.minX, y: rect.minY))
graphPath2.addLine(to: CGPoint.init(x: rect.maxX, y: rect.minY))
graphPath2.addLine(to: CGPoint.init(x: (rect.maxX/2.0), y: (rect.minY/2.0)))
graphPath2.stroke()
let oldPath1=clippingPath.copy() as! UIBezierPath
oldPath1.append(graphPath2)
let startPoint2 = CGPoint(x:(rect.maxX/2.0), y: (rect.maxY/2.0))
let endPoint2 = CGPoint(x:(rect.maxX/2.0), y:rect.minY)
let gradient2=self.getGradient(tiangleNo: 2)
let context2 = UIGraphicsGetCurrentContext()
context2!.drawLinearGradient(gradient2, start: startPoint2, end: endPoint2, options: CGGradientDrawingOptions(rawValue: 0))
But this just adding a triangle inside the previous one.rectis the my UIScreen rectangle
Simple Solution
You can write a function like this
func drawTriangle(point1:CGPoint, point2:CGPoint, point3:CGPoint) {
let path = UIBezierPath()
path.move(to: point1)
path.addLine(to: point2)
path.addLine(to: point3)
path.close()
path.lineWidth = 2.0
UIColor.red.setFill()
path.fill()
}
Draw triagles by calling the function
//Triagle 1
let pointA = CGPoint(x: 0, y: 0)
let pointB = CGPoint(x: 100, y: 0)
let pointC = CGPoint(x: 0, y: 100)
drawTriangle(point1: pointA, point2: pointB, point3: pointC)
//Triagle 2
let pointD = CGPoint(x: 120, y: 0)
let pointE = CGPoint(x: 220, y: 0)
let pointF = CGPoint(x: 220, y: 100)
drawTriangle(point1: pointD, point2: pointE, point3: pointF)
You will get something like this,

UIBezierPath Creating Triangle,Square,Circle Swift

I am attempting to create three shapes: a Circle, Square & Triangle. I have created the circle & square, but am unable to create the triangle. My biggest issue is to keep all three shapes in the center of the screen. The circle and square are fine, but when I attempt to make the triangle it does not work. I am also trying to make the triangle look like a "play button" so that the "tip" of the triangle is facing to the right. Here is the code.
func trainglePathWithCenter(center: CGPoint, side: CGFloat) -> UIBezierPath {
let path = UIBezierPath()
let startX = center.x - side / 2
let startY = center.y - side / 2
path.move(to: CGPoint(x: startX, y: startY))
path.addLine(to: CGPoint(x: startX, y: startY - side))
path.addLine(to: CGPoint(x: startX + side, y: startY + side/2))
path.close()
return path
}
func circlePathWithCenter(center: CGPoint, radius: CGFloat) -> UIBezierPath {
let circlePath = UIBezierPath()
circlePath.addArc(withCenter: center, radius: radius, startAngle: -CGFloat(M_PI), endAngle: -CGFloat(M_PI/2), clockwise: true)
circlePath.addArc(withCenter: center, radius: radius, startAngle: -CGFloat(M_PI/2), endAngle: 0, clockwise: true)
circlePath.addArc(withCenter: center, radius: radius, startAngle: 0, endAngle: CGFloat(M_PI/2), clockwise: true)
circlePath.addArc(withCenter: center, radius: radius, startAngle: CGFloat(M_PI/2), endAngle: CGFloat(M_PI), clockwise: true)
circlePath.close()
return circlePath
}
func squarePathWithCenter(center: CGPoint, side: CGFloat) -> UIBezierPath {
let squarePath = UIBezierPath()
let startX = center.x - side / 2
let startY = center.y - side / 2
squarePath.move(to: CGPoint(x: startX, y: startY))
squarePath.addLine(to: squarePath.currentPoint)
squarePath.addLine(to: CGPoint(x: startX + side, y: startY))
squarePath.addLine(to: squarePath.currentPoint)
squarePath.addLine(to: CGPoint(x: startX + side, y: startY + side))
squarePath.addLine(to: squarePath.currentPoint)
squarePath.addLine(to: CGPoint(x: startX, y: startY + side))
squarePath.addLine(to: squarePath.currentPoint)
squarePath.close()
return squarePath
}
Where am I going wrong with the geometry for the triangle?
You subtracted when you need to add. Remember, +Y is down.
Change:
path.addLine(to: CGPoint(x: startX, y: startY - side))
To:
path.addLine(to: CGPoint(x: startX, y: startY + side))
Here it is running in a Playground:
Here's the full code for the Playground demo:
class Custom: UIView {
override func draw(_ rect: CGRect) {
let path = trainglePathWithCenter(center: self.center, side: self.bounds.width / 2)
path.stroke()
}
func trainglePathWithCenter(center: CGPoint, side: CGFloat) -> UIBezierPath {
let path = UIBezierPath()
let startX = center.x - side / 2
let startY = center.y - side / 2
path.move(to: CGPoint(x: startX, y: startY))
path.addLine(to: CGPoint(x: startX, y: startY + side))
path.addLine(to: CGPoint(x: startX + side, y: startY + side/2))
path.close()
return path
}
}
let custom = Custom(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
custom.backgroundColor = .white
Result triangles
Code in swift5
//TriangleView
extension UIView {
func setRightTriangle(targetView:UIView?){
let heightWidth = targetView!.frame.size.width //you can use triangleView.frame.size.height
let path = CGMutablePath()
path.move(to: CGPoint(x: heightWidth/2, y: 0))
path.addLine(to: CGPoint(x:heightWidth, y: heightWidth/2))
path.addLine(to: CGPoint(x:heightWidth/2, y:heightWidth))
path.addLine(to: CGPoint(x:heightWidth/2, y:0))
let shape = CAShapeLayer()
shape.path = path
shape.fillColor = UIColor.blue.cgColor
targetView!.layer.insertSublayer(shape, at: 0)
}
func setLeftTriangle(targetView:UIView?){
let heightWidth = targetView!.frame.size.width
let path = CGMutablePath()
path.move(to: CGPoint(x: heightWidth/2, y: 0))
path.addLine(to: CGPoint(x:0, y: heightWidth/2))
path.addLine(to: CGPoint(x:heightWidth/2, y:heightWidth))
path.addLine(to: CGPoint(x:heightWidth/2, y:0))
let shape = CAShapeLayer()
shape.path = path
shape.fillColor = UIColor.blue.cgColor
targetView!.layer.insertSublayer(shape, at: 0)
}
func setUpTriangle(targetView:UIView?){
let heightWidth = targetView!.frame.size.width
let path = CGMutablePath()
path.move(to: CGPoint(x: 0, y: heightWidth))
path.addLine(to: CGPoint(x:heightWidth/2, y: heightWidth/2))
path.addLine(to: CGPoint(x:heightWidth, y:heightWidth))
path.addLine(to: CGPoint(x:0, y:heightWidth))
let shape = CAShapeLayer()
shape.path = path
shape.fillColor = UIColor.blue.cgColor
targetView!.layer.insertSublayer(shape, at: 0)
}
func setDownTriangle(targetView:UIView?){
let heightWidth = targetView!.frame.size.width
let path = CGMutablePath()
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x:heightWidth/2, y: heightWidth/2))
path.addLine(to: CGPoint(x:heightWidth, y:0))
path.addLine(to: CGPoint(x:0, y:0))
let shape = CAShapeLayer()
shape.path = path
shape.fillColor = UIColor.blue.cgColor
targetView!.layer.insertSublayer(shape, at: 0)
}
}

Resources