更改 CALayer 的大小也会更改先前添加的图层大小的大小

发布于 2025-01-14 17:28:57 字数 2462 浏览 5 评论 0原文

我正在尝试使用此自定义类绘制 UIImageView,并且我希望能够更改用户绘制的线条的大小和颜色。但每次我更改 CALayer 的大小或颜色时,先前添加的图层的颜色和大小也会随之改变。

class DrawingImageView: UIImageView {
private lazy var path = UIBezierPath()
private lazy var previousTouchPoint = CGPoint.zero
var strokeColor: CGColor!
var strokeWidth: CGFloat!

override init(frame: CGRect) {
    super.init(frame: frame)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)

    let shapeLayer = CAShapeLayer()
    shapeLayer.lineWidth = strokeWidth ?? 4
    shapeLayer.strokeColor = strokeColor ?? UIColor.black.cgColor
    shapeLayer.lineCap = .round
    shapeLayer.lineJoin = .round
    layer.addSublayer(shapeLayer)


    if let location = touches.first?.location(in: self) { previousTouchPoint = location }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesMoved(touches, with: event)
    
    if let location = touches.first?.location(in: self) {
        path.move(to: location)
        path.addLine(to: previousTouchPoint)
        previousTouchPoint = location

        let layerA = layer.sublayers?.last as! CAShapeLayer

        layerA.path = path.cgPath
    }
  }
}

这就是我将该类分配给 tempImageView 的方式

    let mainImageView = UIImageView()
    var tempImgView: DrawingImageView?

    mainImageView.frame = CGRect(x: 0, y: self.view.bounds.height / 7, width: imageWidth, height: imageHieght)
    mainImageView.contentMode = .scaleAspectFit
    mainImageView.layer.zPosition = 2
    mainImageView.isOpaque = false
    mainImageView.backgroundColor = .clear
    mainImageView.isUserInteractionEnabled = true
    mainImageView.tintColor = .clear
    self.view.addSubview(mainImageView)

    func DrawOverImage() {
    
    mainImageView.isHidden = true
    let drawnImageView = DrawingImageView(frame: mainImageView.frame)

    drawnImageView.image = mainImageView.image
    drawnImageView.contentMode = .scaleAspectFit
    drawnImageView.isUserInteractionEnabled = true
    drawnImageView.layer.zPosition = 3
    self.tempImgView?.isUserInteractionEnabled = true
    self.tempImgView = drawnImageView

    self.view.addSubview(tempImgView!)
}

我还尝试创建 CAShapeLayers 数组并将图层添加到数组中,然后分配替换子图层,如 View.layer.subLayers[0] =layers[0] 但这也不起作用,我在网上找不到任何有用的资源。

任何帮助或建议将不胜感激,谢谢。

i'm trying to draw over UIImageView with this custome class and i would like to be able to change the size and color of lines being drawn by user. But every time i change the size or color of CALayer Previously added layer's color and size also changes then.

class DrawingImageView: UIImageView {
private lazy var path = UIBezierPath()
private lazy var previousTouchPoint = CGPoint.zero
var strokeColor: CGColor!
var strokeWidth: CGFloat!

override init(frame: CGRect) {
    super.init(frame: frame)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)

    let shapeLayer = CAShapeLayer()
    shapeLayer.lineWidth = strokeWidth ?? 4
    shapeLayer.strokeColor = strokeColor ?? UIColor.black.cgColor
    shapeLayer.lineCap = .round
    shapeLayer.lineJoin = .round
    layer.addSublayer(shapeLayer)


    if let location = touches.first?.location(in: self) { previousTouchPoint = location }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesMoved(touches, with: event)
    
    if let location = touches.first?.location(in: self) {
        path.move(to: location)
        path.addLine(to: previousTouchPoint)
        previousTouchPoint = location

        let layerA = layer.sublayers?.last as! CAShapeLayer

        layerA.path = path.cgPath
    }
  }
}

this is how i assign that class to tempImageView

    let mainImageView = UIImageView()
    var tempImgView: DrawingImageView?

    mainImageView.frame = CGRect(x: 0, y: self.view.bounds.height / 7, width: imageWidth, height: imageHieght)
    mainImageView.contentMode = .scaleAspectFit
    mainImageView.layer.zPosition = 2
    mainImageView.isOpaque = false
    mainImageView.backgroundColor = .clear
    mainImageView.isUserInteractionEnabled = true
    mainImageView.tintColor = .clear
    self.view.addSubview(mainImageView)

    func DrawOverImage() {
    
    mainImageView.isHidden = true
    let drawnImageView = DrawingImageView(frame: mainImageView.frame)

    drawnImageView.image = mainImageView.image
    drawnImageView.contentMode = .scaleAspectFit
    drawnImageView.isUserInteractionEnabled = true
    drawnImageView.layer.zPosition = 3
    self.tempImgView?.isUserInteractionEnabled = true
    self.tempImgView = drawnImageView

    self.view.addSubview(tempImgView!)
}

i also tried creating array of CAShapeLayers and add layers to an array and then assign replace subLayer like View.layer.subLayers[0] = layers[0] but that also didn't work and i couldn't find any useful resource online.

any help or suggestion would be really appreciated, thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜巴黎 2025-01-21 17:28:57

这是因为您每次都继续相同的路径,因此最新的描边颜色和宽度会应用于整个路径。

在不考虑太多其他逻辑的情况下,我相信您应该每次在 touchesBegan 中初始化一个新路径,并且这个新路径应该在 touchesMoved 中使用,

所以在 touchesBegan,尝试在 layer.addSublayer(shapeLayer) 之后添加 path = UIBezierPath() ,看看这是否能满足您的需求

That is because you are continuing the same path each time and so the latest stroke color and width gets applied to the whole path.

Without looking at much of your other logic, I believe you should initialize a new path each time in your touchesBegan and this new path should be used in touchesMoved

So in touchesBegan, try adding path = UIBezierPath() after layer.addSublayer(shapeLayer) and see if this gives you what you are looking for

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文