英文:
Maintaining UIBezierPath above CAShapeLayer
问题
我有一个添加到CAShapeLayer
的圆圈,和一个使用UIBezierPath
的线。我希望线的位置在圆圈之上。基本上,在drawRect
中,项目的位置将一个接一个地保持。因此,我首先调用drawCircle()
,然后调用drawLine()
,期望线位于圆圈之上。以下是我的代码。
class DrawView: UIView {
override func draw(_ rect: CGRect) {
drawCircle()
drawLine()
}
private func drawCircle() {
if let sublayers = layer.sublayers {
for layer in sublayers where layer.name == "Circle" {
layer.removeFromSuperlayer()
}
}
let circlePath = UIBezierPath(arcCenter: CGPoint(x: bounds.midX, y: 400),
radius: 20.0,
startAngle: 0,
endAngle: CGFloat(Double.pi * 2),
clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.name = "Circle"
shapeLayer.path = circlePath.cgPath
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 3.0
layer.addSublayer(shapeLayer)
}
private func drawLine() {
let path = UIBezierPath()
path.move(to: CGPoint(x:bounds.midX, y:0))
path.addLine(to: CGPoint(x: bounds.midX, y: 400))
path.close()
UIColor.blue.set()
path.lineWidth = 20.0
path.stroke()
}
}
以下是结果。
但是,将线添加到另一个CAShapeLayer
会产生预期的结果,将线添加到圆圈之上。如何在不将线添加到CAShapeLayer
的情况下将线置于圆圈之上呢?
英文:
I have a circle added to CAShapeLayer
and a line with UIBeizerPath
. I want to maintain the position of line to be above circle. Basically in drawRect
, position of the items will be maintained one after the other. So, I call drawCircle()
first and invoke drawLine()
expecting that line has to be on top of the circle. Here is my code.
class DrawView: UIView {
override func draw(_ rect: CGRect) {
drawCircle()
drawLine()
}
private func drawCircle() {
if let sublayers = layer.sublayers {
for layer in sublayers where layer.name == "Circle" {
layer.removeFromSuperlayer()
}
}
let circlePath = UIBezierPath(arcCenter: CGPoint(x: bounds.midX, y: 400),
radius: 20.0,
startAngle: 0,
endAngle: CGFloat(Double.pi * 2),
clockwise: true)
let shapeLayer = CAShapeLayer()
shapeLayer.name = "Circle"
shapeLayer.path = circlePath.cgPath
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 3.0
layer.addSublayer(shapeLayer)
}
private func drawLine() {
let path = UIBezierPath()
path.move(to: CGPoint(x:bounds.midX, y:0))
path.addLine(to: CGPoint(x: bounds.midX, y: 400))
path.close()
UIColor.blue.set()
path.lineWidth = 20.0
path.stroke()
}
}
and below is the result
But, adding the line to another CAShapeLayer
gives the expected result, adds the line on top of circle. How can I bring the line on top of circle without adding the line to a CAShapeLayer
.
答案1
得分: 0
你可以在当前图形上下文中render
圆形图层:
shapeLayer.render(in: UIGraphicsGetCurrentContext()!)
// 而不是
// layer.addSublayer(shapeLayer)
这本质上是以UIBezierPath.stroke
绘制的方式来“绘制”图层。因此,先绘制的东西将出现在后绘制的东西“之下”。
UIGraphicsGetCurrentContext
在这里不会返回 nil,因为你是从 draw
中调用它。
尽管如此,我建议你要么完全使用图层(并在 layoutSubviews
中更新图层),要么*只在 draw
中绘制东西。将两者混合在一起会使代码变得更加混乱,这是我的意见。
英文:
You can render
the circle layer in the current graphics context:
shapeLayer.render(in: UIGraphicsGetCurrentContext()!)
// instead of
// layer.addSublayer(shapeLayer)
This essentially "draws" the layer in the same way that UIBezierPath.stroke
draws things. So the things that are drawn first appear "below" the things that are drawn later.
UIGraphicsGetCurrentContext
will not return nil here because you are calling this from draw
.
That said, I would recommend that you either do everything with layers (and update the layers in layoutSubviews
) or only draw things in draw
. Stick to one of them. Mixing the two makes the code messier, in my opinion.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论