I am making an app where I need to use half circle. But I can't make its frame match the real size of the object. Right now I am trimming the circle but I don't really know you to actually crop the view.
Here is how I trimming the circle:
Circle()
.trim(from: 0, to: 0.5)
.fill(Color.blue)
.background(Color.red)
And I am getting colour red as background twice bigger the my new object.
CodePudding user response:
It's probably better to make your own HalfCircle
that conforms to Shape
instead of trying to bash Circle
into the shape you need. Let's go the extra mile and make it conform to InsettableShape
, in case you want to use it to stroke a border.
import SwiftUI
struct HalfCircle: InsettableShape {
var _inset: CGFloat = 0
func inset(by amount: CGFloat) -> Self {
var copy = self
copy._inset = amount
return copy
}
func path(in rect: CGRect) -> Path {
var path = Path()
// This is a half-circle centered at the origin with radius 1.
path.addArc(
center: .zero,
radius: 1,
startAngle: .zero,
endAngle: .radians(.pi),
clockwise: false
)
path.closeSubpath()
// Since it's the bottom half of a circle, we only want
// to inset the left, right, and bottom edges of rect.
let rect = rect
.insetBy(dx: _inset, dy: 0.5 * _inset)
.offsetBy(dx: 0, dy: -(0.5 * _inset))
// This transforms bounding box of the path to fill rect.
let transform = CGAffineTransform.identity
.translatedBy(x: rect.origin.x 0.5 * rect.size.width, y: 0)
.scaledBy(x: rect.width / 2, y: rect.height)
return path.applying(transform)
}
}
We can use it to draw this:
using this playground:
import PlaygroundSupport
PlaygroundPage.current.setLiveView(HalfCircle()
.inset(by: 20)
.fill(.black)
.background(.gray)
.aspectRatio(2, contentMode: .fit)
.frame(width: 200)
.padding()
)
CodePudding user response:
You can mask it differently using a GeometryReader
:
GeometryReader { proxy in
Circle()
.fill(.blue)
.offset(y: -proxy.size.height) // <- Shows bottom part
.frame(height: proxy.size.width) // <- Makes the circle match frame
.background(.red) // <- Just for testing
}
.aspectRatio(2, contentMode: .fit) // <- Makes the frame ration 2 : 1 (landscape rectangle)
.clipped() // <- Removes out of bound drawings