swift - 如何在父 CALayer 中居中 CALayer

标签 swift calayer uibezierpath

我有一个 UIBezierPaths 数组,我正在循环创建一个 CALayer。生成 CALayer 的代码如下所示:

let layer = CAShapeLayer()
layer.path = path.cgPath
layer.strokeColor = UIColor.gray.cgColor
layer.fillColor = UIColor.clear.cgColor
layer.lineWidth = 3
layer.lineJoin = .bevel
return layer

当返回每一层时,我将其添加到更大的层 (shapeLayer),然后将其添加到 UIView 层。 (希望这是有道理的)。

我遇到的问题是将循环时添加的子层(在 finalShape 内)居中。他们显然有一个使用 path.cgPath 设置的特定路径,我不知道如何在保持他们的位置的同时实现这一点。我真的(显然)对 CALayers 了解不够,无法解决这个问题,我们将不胜感激任何帮助。

谢谢。

-- 如果我向您展示整个代码可能会更有帮助

private let shapeLayer = CALayer()

func bind(shape: Shape) {
    let data = NSKeyedUnarchiver.unarchiveObject(with: shape.strokeData)

    guard let paths = data as? [UIBezierPath] else { return }

    for path in paths {
        let guideLine = drawPathLayer(for: path)
        shapeLayer.addSublayer(guideLine)
    }

    layer.addSublayer(shapeLayer)
}

private func drawPathLayer(for path: UIBezierPath) -> CALayer {
    let layer = CAShapeLayer()
    layer.path = path.cgPath
    layer.strokeColor = UIColor.gray.cgColor
    layer.fillColor = UIColor.clear.cgColor
    layer.lineWidth = 3
    layer.lineJoin = .bevel
    return layer
}

最佳答案

如果您想定位图层(或 View ),执行此操作的时间点至关重要。例如,如果您在 viewDidLoad 中执行此操作,则为时过早,因为父层还没有其最终大小。此外,父层的大小可能会发生变化,因此最好在父层的框架发生变化时将子层居中。您可以使用 CALayer 的子类并覆盖 layoutSublayers 来做到这一点。

它看起来像这样(不是一个正在运行的例子):

class CenteringLayer: CALayer {
    override func layoutSublayers() {
        super.layoutSublayers()
        if let theSublayers = sublayers {
            for s in theSublayers {
                var theFrame = s.frame

                theFrame.origin.x = (bounds.width - theFrame.width) / 2.0
                theFrame.origin.y = (bounds.height - theFrame.height) / 2.0
                s.frame = theFrame
            }
        }
    }
}

注意:您的layer 还必须通过

布局shapeLayer
shapeLayer.frame = layer.bounds

使这项工作。您可以通过为 layer 创建 CALayer 的另一个子类并覆盖 layoutSublayers() 来实现这一点,或者(如果 layer 是 View 层)覆盖 View 类中的 layoutSubviews()。第三个选项可能是覆盖 layoutSublayers(of:)在 View 类中,因为 UIView 始终是其层的委托(delegate)。

但是这些方法有点不优雅,所以你最好考虑减少代码中的层数。例如你应该尽量避免 shapeLayer

如果所有路径都具有相同的属性,您可能只使用一个 CAShapeLayer 连接路径,因为图层可能非常耗费资源。

关于swift - 如何在父 CALayer 中居中 CALayer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57346194/

相关文章:

swift - RxSwift pointfree 风格避免保留循环

ios - awakeFromNib 与 drawRect 中的 CALayer

ios - SKSpriteNode 跟随 bezier 路径旋转

swift - 如何使用Core Graphics编辑高分辨率图像?

ios - 在通过 UIBezierPath 绘制的父 View 上添加 subview

ios - 圆笔触宽度更改动画而不更改圆半径

ios - 如何使用 mapView 和 CLLocationManager 在 iOS Swift 中绘制两个位置之间的方向

ios - 在 iOS/Swift 中使用 withMemoryRebound 时出现 fatal error

swift - Xcode Swift 在 tableView 中显示来自 CloudKit 的数据

iOS:提高图像绘制速度