How to draw a curve path after straight lines in SwiftUI - swift

What I need is to draw a curve like the one shown on the right side of the picture below.
struct DrawingPaths: View {
var body: some View {
Path { path in
path.move(to: CGPoint(x: 0, y: 0))
path.addLine(to: CGPoint(x: 0, y: 300))
path.addLine(to: CGPoint(x: 430, y: 0))
path.addQuadCurve(to: CGPoint(x:430, y: 0), control: CGPoint(x: 300, y: 5))
}
.fill(.blue)
}

That is a quad curve with 2 control points.
struct DrawingPaths: View {
var body: some View {
Path { path in
//Top left
path.move(to: CGPoint(x: 0, y: 0))
//Left vertical bound
path.addLine(to: CGPoint(x: 0, y: 300))
//Curve
path.addCurve(to: CGPoint(x: 430, y: 200), control1: CGPoint(x: 175, y: 350), control2: CGPoint(x: 250, y: 80))
//Right vertical bound
path.addLine(to: CGPoint(x: 450, y: 0))
}
.fill(.blue)
.edgesIgnoringSafeArea(.top)
}
}

Related

Stroking CGPath in swift

I'm trying to add a stroke to `CGPath` in a macOS app with the code below. The issue is that the stroked path can't be filled properly. With the current method, I'm adding the original path on top of the stroked path. This causes the overlapping parts to remain unfilled.
func getPreviewPath(path:CGPath, strokeWidth: CGFloat) ->CGPath{
let window = NSWindow()
let context = NSGraphicsContext(window: window).cgContext
context.setLineCap(CGLineCap(rawValue: 0)!)
context.setLineWidth(strokeWidth)
context.setLineJoin(.bevel)
context.addPath(path)
context.replacePathWithStrokedPath()
context.addPath(path)
return context.path!
}
I've read that this is caused by the even-odd fill rule. But there doesn't seem to be a way to change this.
Here's a minimal example using the stroke() method:
struct ContentView: View {
var body: some View {
Path { path in
path.move(to: CGPoint(x: 20, y: 20))
path.addLine(to: CGPoint(x: 50, y: 100))
path.addLine(to: CGPoint(x: 80, y: 20))
path.addLine(to: CGPoint(x: 120, y: 20))
}
.stroke(style: StrokeStyle(lineWidth: 12.0, lineCap: .round, lineJoin: .bevel))
.padding()
}
}
And this is the result:
Update
Her is a slightly more complex example. It first creates a path containing a stroked path. This path is then filled. The result is the same.
struct ContentView: View {
var body: some View {
Path(createPath())
.fill(.black)
.padding()
}
func createPath() -> CGPath {
let path = CGMutablePath()
path.move(to: CGPoint(x: 20, y: 20))
path.addLine(to: CGPoint(x: 50, y: 100))
path.addLine(to: CGPoint(x: 80, y: 20))
path.addLine(to: CGPoint(x: 120, y: 20))
return path.copy(strokingWithWidth: 12.0, lineCap: .round, lineJoin: .bevel, miterLimit: 10)
}
}

Chat bubble with UI Bezier Path

I want to create the chat bubble with UI Bezier Path but I am new on Bezier Path please help me in this regard. Thanks
private func getRightBottomBubblePath(in rect: CGRect) -> Path {
let width = rect.width
let height = rect.height
let path = Path { p in
p.move(to: CGPoint(x: 25, y: height))
p.addLine(to: CGPoint(x: 20, y: height))
p.addCurve(to: CGPoint(x: 0, y: height - 20),
control1: CGPoint(x: 8, y: height),
control2: CGPoint(x: 0, y: height - 8))
p.addLine(to: CGPoint(x: 0, y: 20))
p.addCurve(to: CGPoint(x: 20, y: 0),
control1: CGPoint(x: 0, y: 8),
control2: CGPoint(x: 8, y: 0))
p.addLine(to: CGPoint(x: width - 21, y: 0))
p.addCurve(to: CGPoint(x: width - 4, y: 20),
control1: CGPoint(x: width - 12, y: 0),
control2: CGPoint(x: width - 4, y: 8))
p.addLine(to: CGPoint(x: width - 4, y: height - 11))
p.addCurve(to: CGPoint(x: width, y: height),
control1: CGPoint(x: width - 4, y: height - 1),
control2: CGPoint(x: width, y: height))
p.addLine(to: CGPoint(x: width + 0.05, y: height - 0.01))
p.addCurve(to: CGPoint(x: width - 11, y: height - 4),
control1: CGPoint(x: width - 4, y: height + 0.5),
control2: CGPoint(x: width - 8, y: height - 1))
p.addCurve(to: CGPoint(x: width - 25, y: height),
control1: CGPoint(x: width - 16, y: height),
control2: CGPoint(x: width - 20, y: height))
}
return path
}
I got this result by using it but I need handle which came out must be in Centre Right.

Need to create custom shape for UIView Swift

I need to create this custom UIView for my project.I need to achieve this
I was doing trial and error by creating, My own custom UIView and then drawing on it.
I'm working on this
My Question is, if I'm able to draw my custom shape, How will I clip-off the remaining white space of the UIView
func drawCustomShape() {
let viewSize = self.frame.size
let buttonSlotRadius = CGFloat(30)
let effectiveViewHeight = viewSize.height - buttonSlotRadius
let path = UIBezierPath()
path.move(to: CGPoint(x: 30, y: 0))
path.addLine(to: CGPoint(x: viewSize.width - 30, y: 0))
path.addArc(withCenter: CGPoint(x: viewSize.width - 30,
y: 30),
radius: 30,
startAngle: .pi * 3 / 2,
endAngle: 0,
clockwise: true)
path.addLine(to: CGPoint(x: viewSize.width, y: effectiveViewHeight))
path.addArc(withCenter: CGPoint(x: viewSize.width - 30,
y: effectiveViewHeight - 30),
radius: 30,
startAngle: 0,
endAngle: .pi / 2,
clockwise: true)
path.addLine(to: CGPoint(x: viewSize.width / 4, y: effectiveViewHeight))
// close path join to origin
path.close()
UIColor.secondarySystemFill.setFill()
path.fill()
path.lineWidth = 6.0
path.stroke()
}
You can use UIView with clear background color, and use CAShapeLayer with desired path like this:
extension UIView {
func drawCustomShape() {
let cornerRadius: CGFloat = 18.0
let shapeOffset = self.frame.size.height * 0.2
//create shape layer
let shapeLayer = CAShapeLayer()
shapeLayer.frame = self.bounds
shapeLayer.lineWidth = 1.0
shapeLayer.fillColor = UIColor.white.cgColor
self.layer.addSublayer(shapeLayer)
//create path
let path = UIBezierPath()
//top left point
path.move(to: CGPoint(x: 0, y: cornerRadius))
//top left corner
path.addQuadCurve(to: CGPoint(x: cornerRadius, y: 0),
controlPoint: CGPoint(x: 0, y: 0))
//top right point
path.addLine(to: CGPoint(x: self.frame.size.width - cornerRadius, y: 0))
//top right corner
path.addQuadCurve(to: CGPoint(x: self.frame.size.width, y: cornerRadius),
controlPoint: CGPoint(x: self.frame.size.width, y: 0))
//bottom right point
path.addLine(to: CGPoint(x: self.frame.size.width, y: self.frame.size.height - shapeOffset - cornerRadius))
//bottom right corner
path.addQuadCurve(to: CGPoint(x: self.frame.size.width - cornerRadius, y: self.frame.size.height - shapeOffset),
controlPoint: CGPoint(x: self.frame.size.width, y: self.frame.size.height - shapeOffset))
//bottom left
path.addLine(to: CGPoint(x: cornerRadius, y: self.frame.size.height))
//bottom left corner
path.addQuadCurve(to: CGPoint(x: 0, y: self.frame.size.height - cornerRadius),
controlPoint: CGPoint(x: 0, y: self.frame.size.height))
path.close()
shapeLayer.path = path.cgPath
}
Usage:
myView.drawCustomShape()
Result:

Xcode Swift, Keyframe animation has unwanted delay between animations loops on a bezier curve

Im attempting to animate a UIView along an oval using a bezier curve. The code works except that there is a delay between each loop of the animation. I'm at a loss as to what is causing this.
let myView = UIView()
myView.backgroundColor = UIColor.blue
myView.frame = CGRect(x: 0, y:0, width: 30, height: 30)
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 200, height: 200))
let animation = CAKeyframeAnimation(keyPath: "position")
animation.path = path.cgPath
animation.repeatCount = 1000
animation.duration = 1
myView.layer.add(animation, forKey: "animate along path")
Found a solution. The pause between animation loops only takes place when making a path with the UIBezierPath(ovalIn:) constructor. There's no delay when manually making your own path. So I made my own oval.
Replaced this
let path = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: 200, height: 200))
with this
let rect = CGRect(x: 0, y: 0, width: 200, height: 200)
let path = UIBezierPath()
path.move(to: CGPoint(x: rect.maxX, y: rect.midY))
path.addQuadCurve(to: CGPoint(x: rect.midX, y: rect.maxY), controlPoint: CGPoint(x: rect.maxX, y: rect.maxY))
path.addQuadCurve(to: CGPoint(x: rect.minX, y: rect.midY), controlPoint: CGPoint(x: rect.minX, y: rect.maxY))
path.addQuadCurve(to: CGPoint(x: rect.midX, y: rect.minY), controlPoint: CGPoint(x: rect.minX, y: rect.minY))
path.addQuadCurve(to: CGPoint(x: rect.maxX, y: rect.midY), controlPoint: CGPoint(x: rect.maxX, y: rect.minY))

How can i make a path like the number 8 (SpriteKit, Swift)

I'm trying to create a path for an object to follow that is in the shape of the number 8. Is it possible to create a path with curves like the shape of a number 8?
If it's not, how would you suggest I do this?
Thanks (:
SKPhysicsBody Path Generator is powerful tool that you can create with him what you want!
very comfortable and easy to create your path!
Basic Instruction
Drag and drop the sprite image into drop zone.
Start drawing path by clicking on coordinates.
The link
Here's a simple example:
var curve = UIBezierPath()
let startPoint = CGPoint(x: 100, y: 50)
curve.moveToPoint(startPoint)
// top right
curve.addCurveToPoint(CGPoint(x: 100, y: 250),
controlPoint1: CGPoint(x: 200, y: 50),
controlPoint2: CGPoint(x: 200, y: 250))
// bottom left
curve.addCurveToPoint(CGPoint(x: 100, y: 450),
controlPoint1: CGPoint(x: 0, y: 250),
controlPoint2: CGPoint(x: 0, y: 450))
// bottom right
curve.addCurveToPoint(CGPoint(x: 100, y: 250),
controlPoint1: CGPoint(x: 200, y: 450),
controlPoint2: CGPoint(x: 200, y: 250))
// top left
curve.addCurveToPoint(CGPoint(x: 100, y: 50),
controlPoint1: CGPoint(x: 0, y: 250),
controlPoint2: CGPoint(x: 0, y: 50))
curve.closePath()