UIBezierPath的颜色和线宽错误

ssa*_*ngi 5 ios uibezierpath swift3

我在使用UIBezierPath时遇到了一个奇怪的问题,我的颜色和线宽没有正确呈现.

我正在绘制一系列具有主要和次要渐变的线条(如尺子).主要渐变是长度更长的线条......

主要渐变:颜色红色和线宽:2.0次要渐变:颜色黄色和线宽:0.0(根据规格最细的线)

滑块

    override func draw(in ctx: CGContext) {
    if let _ = cameraControlSlider {
        guard gradationValues.count >= 0 else {
            return
        }

        let frame = CGRect(x: insetBy, y: 0, width: bounds.width - insetBy, height: bounds.height)
        ctx.clear(frame)

        let startx = Int(frame.origin.x)
        let endx = Int(frame.origin.x + frame.width)

        let incrementWidth = (endx - startx) / (gradationValuesOnScreen + 1)

        var counter = 1
        var x = startx + counter * incrementWidth

        while x < endx {

            var y1 = Int(frame.origin.y)
            var y2 = Int(frame.origin.y) + Int(frame.height)
            var lineWidth: Float = 2.0
            var color = UIColor.red

            if counter % majorGradationInterval != 1 {
                y1 = Int(frame.origin.y) + Int(frame.height / 4)
                y2 = Int(frame.origin.y + frame.height) - Int(frame.height / 4)
                lineWidth = 0.0
                color = UIColor.yellow
            }

            ctx.addPath(drawLine(in: ctx, x1: x, y1: y1, x2: x, y2: y2, color: color, lineWidth: lineWidth))
            counter += 1
            x = startx + counter * incrementWidth
        }
    }
}

func drawLine(in ctx: CGContext, x1: Int, y1: Int, x2: Int, y2: Int, color: UIColor, lineWidth: Float) -> CGPath {
    let path = UIBezierPath()

    ctx.setStrokeColor(color.cgColor)

    path.lineWidth = CGFloat(lineWidth)
    path.move(to: CGPoint(x: x1, y: y1))
    path.addLine(to: CGPoint(x: x2, y: y2))
    path.close()

    ctx.strokePath()

    return path.cgPath
}
Run Code Online (Sandbox Code Playgroud)

基本上我希望较长的线条具有红色和较粗的线宽,但颜色看起来是倒置的,线条宽度似乎没有任何影响.

从绘图功能可以看出,没有UIColor红色与较小的线长度相关联.我已经尝试在创建路​​径之前设置笔触颜色,但这似乎不起作用.

Rob*_*Rob 2

这里有几个问题,但关键问题是drawLine创建UIBezierPath并调用strokePath. 但strokePath不会抚摸UIBezierPath您刚刚创建的路径,而是抚摸添加到该上下文的先前路径。但由于您直到从 返回后才将该行添加到上下文中drawLine,因此所有内容都会减少一。另外,由于您将所有这些行添加到上下文中(而不是替换路径),因此您正在重复地重绘相同的行。

您可以通过调用drawLine而不是修复它addPath(drawLine(...)

override func draw(in ctx: CGContext) {
    ...

    while x < endx {
        ...

        drawLine(in: ctx, x1: x, y1: y1, x2: x, y2: y2, color: color, lineWidth: lineWidth)

        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

并且drawLine不返回任何内容,但实际上只是绘制它:

func drawLine(in ctx: CGContext, x1: Int, y1: Int, x2: Int, y2: Int, color: UIColor, lineWidth: Float) {
    let path = UIBezierPath()

    ctx.saveGState()
    ctx.setStrokeColor(color.cgColor)
    ctx.setLineWidth(CGFloat(lineWidth))
    path.move(to: CGPoint(x: x1, y: y1))
    path.addLine(to: CGPoint(x: x2, y: y2))
    ctx.addPath(path.cgPath)
    ctx.strokePath()
    ctx.restoreGState()
}
Run Code Online (Sandbox Code Playgroud)

请注意,我正在保存和恢复图形上下文,以便每次都可以绘制新的线段路径。另外,由于我正在抚摸上下文的路径,因此我正在调用setLineWidth上下文,而不是路径。另外,这里没有显示,我发现如果我抚摸宽度为零的黄线,它们不会出现,所以我使用了1:

示例图像

请注意,如果这是一个UIView子类,您可以进一步简化它(只需UIBezierPath直接描边而不是与 CoreGraphics 搞乱,您可以制作它@IBDesignable,等等)。但如果你要实现draw(in:),我可能会做类似上面的事情。