2016-11-30 38 views
3

我在UIBezierPath中出現奇怪的問題,其中我的顏色和線條寬度未正確呈現。UIBezierPath錯誤的顏色和線條寬度

我正在繪製一系列具有主要和次要漸變的線條(如標尺)。主要的灰度與較長長度的線...

主要定級:顏色紅色&線寬:2.0 次要定級:顏色黃色&線寬:(根據規格最薄線)0.0

slider

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 
} 

本質上我想要更長的線條是紅色和更寬的線條寬度,但顏色看起來倒置,線條寬度似乎沒有任何影響。

從繪圖函數可以看出,沒有UIColor紅色與較小的行長度相關聯。我已經嘗試在創建路​​徑之前設置描邊顏色,但似乎並不奏效。

回答

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) 

     ... 
    } 
} 

而且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() 
} 

注意,我已把並恢復圖形上下文,以便每次都可以繪製新的線段線段路徑。另外,由於我正在觸摸上下文的路徑,所以我在上下文中調用setLineWidth,而不是路徑。另外,這裏沒有顯示,我發現,如果我撫摸着黃線爲零的寬度,他們並沒有出現,所以我用1:

example image

注意,如果這是一個UIView子你可以進一步簡化它(只需直接敲擊UIBezierPath而不是搞亂CoreGraphics,你可以使它變成@IBDesignable等等)。但是如果你要實現draw(in:),我可能會做類似上面的事情。

+0

這是完美的@Rob。這說得通。但是,您提到自從我們添加到上下文後它正在重繪。在保存G狀態的同時,上面提到的更改會不會發生。另外,你什麼時候使用path.stroke vs ctx.stroke。 Path.stroke給了我錯誤的無效上下文,這就是爲什麼我沒有使用它。 UIView方法聽起來很有趣。我必須嘗試一下。非常感謝。 – ssarangi

+0

重新繪製,因爲我們正在保存和恢復上下文,所以路徑被重置爲先前的無路徑狀態(例如,保存上下文,添加路徑,描邊它,並將其恢復到無路徑狀態,然後重複)。 – Rob

+0

Re'path.stroke',你在圖形上下文中使用它(例如,在'UIView'子類的'draw(_ rect:)')中。我非常喜歡'UIView'子類的方法,因爲代碼更簡單,您可以像添加任何其他'UIView'一樣將它添加到視圖層次結構中,並且如果合適的話,將其設置爲'@ IBDesignable',然後在你的故事板。但是你可能已經在'draw(in:)'模式中寫了足夠多的東西,而這些東西比需要的更多。幸運的是,這兩種方法都很好。 – Rob