仅在边缘上描边CGPath

时间:2016-05-14 04:29:15

标签: swift geometry cgaffinetransform cgpath

我正在使用Swift制作游戏,我有一个任意角度的CGPath。现在让我们假设它总是一条直线。

line

我想要创建的是这样的:

line2

我已经尝试过一种非常简单的方法,即在黑色的粗线条上进行描边,复制路径,然后在背景颜色的稍微细的线宽处再次抚摸它。这给出了正确的外观,但最终我需要中间透明。

我认为这可以通过使用" parent"的转换来实现。路径(在中间),但我不知道该怎么做。沿着单个轴的简单平移不会起作用,因为路径是一个角度。我认为我需要使用其端点来计算路径的斜率,并使用一些数学来找到距离父路径一定垂直距离的点。但我真的不确定如何做到这一点。有任何提示,还是有其他方法可以做到这一点?

修改: 我确实尝试使用CGPathCreateCopyByStrokingPath,但当然是描边整个路径,我真的需要创建两个边 - 而不是结束。我想要这样的事情:

path3

1 个答案:

答案 0 :(得分:2)

使用CGPathCreateCopyByStrokingPath创建一个新路径,在您指定的偏移处概述当前路径(偏移量是lineWidth的一半)。然后抚摸那条新路。

更新

这是一个采用线段(作为一对点)和偏移量的函数,并返回与原始线平行且偏移的新线段。

func lineSegment(segment: (CGPoint, CGPoint), offsetBy offset: CGFloat) -> (CGPoint, CGPoint) {
    let p0 = segment.0
    let p1 = segment.1

    // Compute (dx, dy) as a vector in the direction from p0 to p1, with length `offset`.
    var dx = p1.x - p0.x
    var dy = p1.y - p0.y
    let length = hypot(dx, dy)
    dx *= offset / length
    dy *= offset / length

    // Rotate the vector one quarter turn in the direction from the x axis to the y axis, so it's perpendicular to the line segment from p0 to p1.
    (dx, dy) = (-dy, dx)

    let p0Out = CGPointMake(p0.x + dx, p0.y + dy)
    let p1Out = CGPointMake(p1.x + dx, p1.y + dy)
    return (p0Out, p1Out)
}

这是一个使用它的游乐场示例:

func stroke(segment: (CGPoint, CGPoint), lineWidth: CGFloat, color: UIColor) {
    let path = UIBezierPath()
    path.moveToPoint(segment.0)
    path.addLineToPoint(segment.1)
    path.lineWidth = lineWidth
    color.setStroke()
    path.stroke()
}

let mainSegment = (CGPointMake(20, 10), CGPointMake(50, 30))
UIGraphicsBeginImageContextWithOptions(CGSizeMake(80, 60), true, 2)
UIColor.whiteColor().setFill(); UIRectFill(.infinite)
stroke(mainSegment, lineWidth: 1, color: .blackColor())
stroke(lineSegment(mainSegment, offsetBy: 10), lineWidth: 2, color: .redColor())
stroke(lineSegment(mainSegment, offsetBy: -10), lineWidth: 2, color: .blueColor())
let image = UIGraphicsGetImageFromCurrentImageContext()
XCPlaygroundPage.currentPage.captureValue(image, withIdentifier: "image")

结果:

parallel line segments