Setting line cap style doesn't work UIBezierPath - ios

This is my code:
let cross = UIBezierPath()
cross.move(to: CGPoint(x: skull.bounds.maxX, y: skull.bounds.minY))
cross.addLine(to: CGPoint(x: skull.bounds.minX, y: skull.bounds.maxY))
cross.close()
UIColor.red.set()
cross.lineWidth = 3.0
cross.lineCapStyle = .round
cross.stroke()
I want to round the end of the line, but it's still square, how should I do it?

just tested on PlayGround, Hope it will help
let cross = UIBezierPath()
cross.moveToPoint(CGPoint(x: 10, y: 100)) // your point
cross.addLineToPoint(CGPoint(x: 100, y: 10)) // your point
cross.closePath()
cross.lineWidth = 23.0
cross.lineJoinStyle = .Round
cross.stroke()
Swift 5.0
let cross = UIBezierPath()
cross.move(to: CGPoint(x: 10, y: 100)) // your point
cross.addLine(to: CGPoint(x: 100, y: 10)) // your point
cross.close()
cross.lineWidth = 23.0
cross.lineJoinStyle = .round
cross.stroke()
Result

The line cap style configures the style of the line ending. You have closed path, i.e. you have no line ending.
You are probably looking for the line join style, which affects all "corners" or "vertexes" of a path.
Alternatively, if you just want a straight, don't close the path. Otherwise you get two line segments: one from the starting point to the end point and another one back to the start.

Swift 4.1 update to Umair Afzal's code:
let cross = UIBezierPath()
cross.move(to: CGPoint(x: 10, y: 100)) // your point
cross.addLine(to: CGPoint(x: 100, y: 10)) // your point
cross.lineWidth = 12
cross.lineCapStyle = .round
cross.stroke()

Related

How do I make sure that my label is always centered on the line?

I tried to take the coordinates of the LinePath.bounds.Max and line Path.bounds.Maxi , but it does not give the desired result
enter code here
private func addLine(start:CGPoint, end: CGPoint) {
let linePath = UIBezierPath()
linePath.move(to: start)
linePath.addLine(to: end)
line.path = linePath.cgPath
line.strokeColor = UIColor.white.cgColor
line.lineWidth = 4
distanceLabel.text = String(distanceForLabel)
distanceLabel.textColor = .black
distanceLabel.frame = CGRect(x: linePath.bounds.midX,
y: line.bounds.midY,
width: linePath.bounds.width / 2,
height: 20)
uiImageView.addSubview(distanceLabel)
One problem is that your are setting the y value for the label's frame to:
y: line.bounds.midY
but it should be:
y: linePath.bounds.midY
However, your frame code puts the top-left corner of the label at the midpoint of the line.
If you want the center of the label to be centered on the line, use this for your label's frame:
distanceLabel.frame.size = CGSize(width: linePath.bounds.width / 2.0, height: 20.0)
distanceLabel.center = CGPoint(x: linePath.bounds.midX, y: linePath.bounds.midY)

Is it possible to show/stroke only a portion of a UIBezierPath?

I have a UIBezierPath shape (comprised of various line segments) already defined, but depending on the scenario, I only want certain portions of it visible. Is this possible?
I was initially thinking along the lines of how when you animate a UIBezierPath, you can animate from a .fromValue to a .toValue. Can I set some sort of "current value" (which I see exists, but only as a getOnly property) to accomplish something similar, outside of an animation context?
Another way I thought of was to just treat my path as a sort of "template" path, and then break it up into various subpaths, but I'm hoping there is an easier/more direct way (unless this method is easier than I anticipate...).
UIBezierPath doesn't have that, but if you add the path to a CAShapeLayer, you can control the strokeStart and strokeEnd.
Try this in a playground:
let path = UIBezierPath()
path.move(to: .zero)
path.addLine(to: CGPoint(x: 10, y: 10))
path.addLine(to: CGPoint(x: 20, y: 0))
path.addLine(to: CGPoint(x: 30, y: 10))
let layer = CAShapeLayer()
layer.path = path.cgPath
layer.strokeColor = UIColor.red.cgColor
layer.fillColor = UIColor.clear.cgColor
// Note these lines
layer.strokeStart = 0.2 // start at 20% of the way
layer.strokeEnd = 0.8 // end at 80% of the way
layer.lineWidth = 2
let view = UIView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
view.layer.addSublayer(layer)
The above produces:
Without the two lines that set the stroke start and end, the view looks like:

Slice an SKShapeNode into two

Is there an easy method to slice an SKShapeNode into 2 seperate SKShapeNodes?
In this example I have created an SKShapeNode using a closed bezier path as well as a single line.
let squareShape = SKShapeNode()
squareShape.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 256, height: 256), cornerRadius: 10).cgPath
squareShape.position = CGPoint(x: frame.midX-128, y: frame.midY+200-128)
squareShape.fillColor = UIColor.green
squareShape.strokeColor = UIColor.blue
squareShape.lineWidth = 2
addChild(squareShape)
let lineShape1 = SKShapeNode()
let line1 = UIBezierPath()
line1.move(to: CGPoint(x: -200, y: 300))
line1.addLine(to: CGPoint(x: 200, y: 100))
lineShape1.path = line1.cgPath
lineShape1.strokeColor = UIColor.white
lineShape1.lineWidth = 2
addChild(lineShape1)
How can I transform the existing SKShapeNode into 2 seperate SKShapeNodes separated by the line?
I need to be able to do this with varying line positions and shapes types (or even with multiple shapes and a single line).
Thanks

Use PhysicsBody with SKShapenode line. Swift, iOS, SpriteKit

I need to add simple line using ShapeBody to interact with.
I'am trying code below, by Xcode gives me next response:
PhysicsBody: Could not create physics body.
let testPath = UIBezierPath()
testPath.move(to: CGPoint(x:-100, y: 200))
testPath.addLine(to: CGPoint(x:100, y: 200))
let testShape = SKShapeNode()
testShape.path = testPath.cgPath
testShape.position = CGPoint(x:0, y:250)
testShape.zPosition = 5
testShape.lineWidth = 5
testShape.strokeColor = .red
testShape.physicsBody = SKPhysicsBody(polygonFrom: testPath.cgPath)
Used edgeChainFrom instead of polygonFrom, and it works!
testShape.physicsBody = SKPhysicsBody(edgeChainFrom: testPath.cgPath)
A path cannot intersect any of its lines with a SKPhysicsBody, your line needs to be a thin rectangle
let testPath = UIBezierPath()
testPath.move(to: CGPoint(x:-100, y: 200))
testPath.addLine(to: CGPoint(x:100, y: 200))
testPath.addLine(to: CGPoint(x:100, y: 201))
testPath.addLine(to: CGPoint(x:-100, y: 201))
testPath.close()
let testShape = SKShapeNode()
testShape.path = testPath.cgPath
testShape.position = CGPoint(x:0, y:250)
testShape.zPosition = 5
testShape.lineWidth = 5
testShape.strokeColor = .red
testShape.physicsBody = SKPhysicsBody(polygonFrom: testPath.cgPath)

How do I draw a triangle with a corner radius?

I am trying to draw a triangle like this one exactly
Can someone guide me how to achieve this as I tried a lot with no success?
my worst case scenario is to use a image but I don't want to do that.
Thanks a lot!
Maybe you should try this:
let trianglePath = UIBezierPath()
trianglePath.lineJoinStyle = .round
trianglePath.lineWidth = 25
trianglePath.move(to: CGPoint(x: 5.0, y: 10.0))
trianglePath.addLine(to: CGPoint(x: 130, y: 280.0))
trianglePath.addLine(to: CGPoint(x: 265.0, y: 10.0))
trianglePath.close()
That gives you this in Playground:

Resources