2 CAShapeLayer中的对齐线虚线图案

问题描述 投票:0回答:1

我正在呼唤您,核心动画之神!我正在尝试在iOS中显示形状。这个想法是绘制一个内部和外部带有虚线的正方形,如以下通过Sketch应用创建的图像所示。

square shape with two dashed borders created in sketch

我正在实现它,创建了三层,一层用于外部笔触,一层用于内部笔触,一层用于填充。这是我的代码:

        // setup square properties
        let lineDashPattern = [10, 5]
            .map({ NSNumber(value: $0) })
        let strokeWidth = CGFloat(5)
        let frame = CGRect(
            x: 40,
            y: 40,
            width: 119,
            height: 119)
        let pathBox = CGRect(
            x: 0,
            y: 0,
            width: frame.size.width,
            height: frame.size.width)

        // Create the container layer
        let square = CALayer()
        square.frame = frame

        // create the fill
        let fill = CAShapeLayer()
        fill.frame = pathBox
        fill.fillColor = UIColor.lightGray.cgColor
        fill.path = UIBezierPath(rect: frame).cgPath

        // Creater the inner border
        let innerBorder = CAShapeLayer()
        innerBorder.frame = frame
        innerBorder.lineWidth = strokeWidth
        innerBorder.strokeColor = UIColor.blue.cgColor
        innerBorder.lineDashPattern = lineDashPattern
        innerBorder.fillColor = UIColor.clear.cgColor
        innerBorder.path = UIBezierPath(rect: pathBox)
            .cgPath
            .contract(by: strokeWidth / 2)

        // Create the outer border
        let outerBorder = CAShapeLayer()
        outerBorder.frame = frame
        outerBorder.lineWidth = strokeWidth
        outerBorder.strokeColor = UIColor.red.cgColor
        outerBorder.lineDashPattern = lineDashPattern
        outerBorder.fillColor = UIColor.clear.cgColor
        outerBorder.path = UIBezierPath(rect: pathBox)
            .cgPath
            .contract(by: -(strokeWidth / 2))

        // add all to screen
        square.addSublayer(fill)
        square.addSublayer(innerBorder)
        square.addSublayer(outerBorder)
        view.layer.addSublayer(square)

我还在CGPath上创建了以下扩展,以方便缩放形状的路径以创建笔画:

extension CGPath {
    func contract(by value: CGFloat) -> CGPath {
        let finalBoundingBox = boundingBox.insetBy(
            dx: value,
            dy: value)
        let scaleFactor: CGFloat = finalBoundingBox.width / boundingBox.width

        var scaleTransform = CGAffineTransform.identity
            .centerScaledBy(x: scaleFactor, y: scaleFactor, bounds: boundingBox)

        return copy(using: &scaleTransform)!
    }

}

extension CGAffineTransform {

    func centerScaledBy(x:CGFloat, y:CGFloat, bounds: CGRect) -> CGAffineTransform {
        let center = bounds.center
        var xform  = self

        xform = xform.concatenating(CGAffineTransform(translationX: -center.x, y: -center.y))
        xform = xform.concatenating(CGAffineTransform(scaleX: x, y: y))
        xform = xform.concatenating(CGAffineTransform(translationX: center.x, y: center.y))

        return xform
    }
}

extension CGRect {

    var center: CGPoint {
        return CGPoint(x: self.midX, y: midY)
    }
}

但是,结果不同,我得到完全未对齐的笔划破折号,如:

square shape with two dashed borders created in with core animation

我猜想Sketch在引擎盖下使用了Core Animation图层,所以草图可以完成的所有工作都应该可以通过代码复制,对吧?

提前感谢。

ios swift core-animation
1个回答
0
投票

Sketch应用示例中的破折号看起来不像普通破折号–请注意,拐角处的破折号段的长度不均匀。要重新创建它,我只需要使用八个单独的层:四个用于四个内部边缘,然后另外四个用于外部边缘。我会用lineDashPhase来使外边缘的虚线图案与内边缘的虚线图案匹配。

© www.soinside.com 2019 - 2024. All rights reserved.