维护 UIBezierPath 在 CAShapeLayer 之上。

huangapple go评论119阅读模式
英文:

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()
    }
}

以下是结果。

维护 UIBezierPath 在 CAShapeLayer 之上。

但是,将线添加到另一个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

维护 UIBezierPath 在 CAShapeLayer 之上。

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.

huangapple
  • 本文由 发表于 2023年3月31日 17:14:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/75896744.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定