使用UIBezierPath绘制圆角使用UIBezierPath
我有一个设计元素,我很难搞清楚;希望有人能够指引我走向正确的方向。我试图建立的元素就像这样;使用UIBezierPath绘制圆角使用UIBezierPath
实际上,它是一个圆角矩形左侧,顶部的行程,和右侧(底部应该没有中风)。
我已经涉足使用下面的代码;
// Create the rounded rectangle
let maskPath = UIBezierPath(roundedRect: myView.bounds, byRoundingCorners: [.topLeft, .topRight], cornerRadii: CGSize(width: 4.0, height: 4.0))
// Setup a shape layer
let shape = CAShapeLayer()
// Create the shape path
shape.path = maskPath.cgPath
// Apply the mask
myView.layer.mask = shape
随后,我使用以下方法在矩形上绘制笔划;
// Add border
let borderLayer = CAShapeLayer()
borderLayer.path = maskPath.cgPath
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = UIColor.white.cgColor
borderLayer.lineWidth = 2.0
borderLayer.frame = self.bounds
self.layer.addSublayer(borderLayer)
产生以下图像;
我已经无法找出如何可以卸下底部行程或画使用UIBezierPath()的项目,但在某种程度上四舍五入的角落,这将是相同的到圆角矩形(我在同一视图中使用另一个圆角矩形用于不同的目的,并且圆角将需要相同)。
谢谢!
请勿使用形状图层。使用图层(或视图)。绘制UIBezierPath的路径并对其进行描边,然后通过绘制并用.clear
混合模式对其进行描边来清除底线。
结果:
代码(修改为所需的;我在这里使用一个明确的UIView绘制的形状作为其draw
代码):
let p = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .topRight],
cornerRadii: CGSize(width: 4.0, height: 4.0))
UIColor.white.setStroke()
p.stroke()
let p2 = UIBezierPath()
p2.move(to: CGPoint(x:0, y:self.bounds.height))
p2.addLine(to: CGPoint(x:self.bounds.width, y:self.bounds.height))
p2.lineWidth = 2
p2.stroke(with: .clear, alpha: 1)
EDIT另一种方法是在绘制圆角矩形之前一直要剪掉底线区域:
let p1 = UIBezierPath(rect: CGRect(origin:.zero,
size:CGSize(width:self.bounds.width, height:self.bounds.height-2)))
p1.addClip()
let p = UIBezierPath(roundedRect: self.bounds,
byRoundingCorners: [.topLeft, .topRight],
cornerRadii: CGSize(width: 4.0, height: 4.0))
UIColor.white.setStroke()
p.stroke()
CGMutablePath
方法addArc(tangent1End:tangent2End:radius:transform:)
旨在轻松制作圆角。
extension CGMutablePath {
static func bottomlessRoundedRect(in rect: CGRect, radius: CGFloat) -> CGMutablePath {
let path = CGMutablePath()
path.move(to: CGPoint(x: rect.minX, y: rect.maxY))
path.addArc(tangent1End: CGPoint(x: rect.minX, y: rect.minY), tangent2End: CGPoint(x: rect.maxX, y: rect.minY), radius: radius)
path.addArc(tangent1End: CGPoint(x: rect.maxX, y: rect.minY), tangent2End: CGPoint(x: rect.maxX, y: rect.maxY), radius: radius)
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
return path
}
}
一旦你的方法,最好使用自定义视图来管理CAShapeLayer
,因此它可以自动适应大小的变化。演示:
class MyFrameView: UIView {
override class var layerClass: AnyClass { return CAShapeLayer.self }
override func layoutSubviews() {
super.layoutSubviews()
let layer = self.layer as! CAShapeLayer
layer.lineWidth = 2
layer.strokeColor = UIColor.white.cgColor
layer.fillColor = nil
layer.path = CGMutablePath.bottomlessRoundedRect(in: bounds.insetBy(dx: 10, dy: 10), radius: 8)
}
}
import PlaygroundSupport
let view = UIView(frame: CGRect(x: 0, y: 0, width: 120, height: 60))
view.backgroundColor = #colorLiteral(red: 0.7034167647, green: 0.4845994711, blue: 0.6114708185, alpha: 1)
let frameView = MyFrameView(frame: view.bounds)
frameView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
view.addSubview(frameView)
let label = UILabel(frame: view.bounds)
label.text = "Hello"
label.textColor = .white
label.textAlignment = .center
view.addSubview(label)
PlaygroundPage.current.liveView = view
结果:
我很高兴你添加了这个。我们以前常常在贝塞尔路径有自动圆角之前这样做!我没有在这里使用它的唯一原因是我想坚持OP开始的确切的贝塞尔路径,因为这是问题规定的一部分。 – matt
,完美的工作!谢谢,@matt!我太过于复杂了;我没有意识到我可以用'.clear'混合模式进行中风。现在有道理! – ZbadhabitZ
还有另一种方法,即在绘制圆角矩形之前剪切。也许我也应该证明这一点。 – matt
添加代码以演示第二种方式,裁剪。在这种情况下,我更喜欢裁剪。它更容易控制。 – matt