覆盖绘图应用程序的drawRect

Posted

技术标签:

【中文标题】覆盖绘图应用程序的drawRect【英文标题】:Overriding drawRect for drawing app 【发布时间】:2015-07-16 02:13:21 【问题描述】:

我正在构建一个演示绘图应用程序。我正在使用 touchesMoved:withEvent 来收集我的积分并将它们添加到 CGMutablePathRef。为了描边路径,我重写了 DrawRect,将路径添加到上下文中并描边路径:

   override func drawRect(rect: CGRect) 
    self.backgroundColor?.set()
    UIRectFill(rect)

    let context : CGContextRef = UIGraphicsGetCurrentContext()
    for line in pathArray 
        CGContextAddPath(context, line.structPath)
        CGContextSetLineWidth(context, line.structLineWidth)
        CGContextSetStrokeColorWithColor(context, line.structLineColor.CGColor)
        CGContextSetAlpha(context, lineOpacity)

    
    CGContextSetLineCap(context, kCGLineCapRound)
    CGContextStrokePath(context)

    self.empty = false


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 
    if let touch = touches.first as UITouch! 
        previousPoint = touch.previousLocationInView(self)
        previousPreviousPoint = touch.previousLocationInView(self)
        currentPoint = touch.locationInView(self)
    
    self.touchesMoved(touches, withEvent: event)


override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) 


     if let touch = touches.first as UITouch! 

        previousPreviousPoint = previousPoint
        previousPoint = touch.previousLocationInView(self)
        currentPoint = touch.locationInView(self)

        let mid1 : CGPoint = getMidPoint(previousPoint, p2: previousPreviousPoint)
        let mid2 : CGPoint = getMidPoint(currentPoint, p2: previousPoint)

        let subpath : CGMutablePathRef = CGPathCreateMutable()
        CGPathMoveToPoint(subpath, nil, mid1.x, mid1.y)
        CGPathAddQuadCurveToPoint(subpath, nil, previousPoint.x, previousPoint.y, mid2.x, mid2.y)

        let bounds : CGRect = CGPathGetBoundingBox(subpath)
        let drawBox : CGRect = CGRectInset(bounds, -2.0 * lineWidth, -2.0 * lineWidth)

        let newLine = line(newPath: subpath)
        pathArray.append(newLine)
        self.setNeedsDisplayInRect(drawBox)
    

上面的代码按预期工作,除了我看到一个意外的结果。获取 bandbox 并设置 CGRectInset 的“draw box”会更改已绘制的其他路径的 lineColor:

我了解(某种程度上)为什么会发生这种情况,但无法找到解决此问题的方法。任何建议将不胜感激!

【问题讨论】:

“更灵活”对您来说究竟意味着什么?你想要什么额外的功能? 我在重绘视图时遇到了真正的问题。当我想改变描边颜色时,整个绘图都会改变颜色。当我尝试删除最后添加的路径时,它不会重绘。我想一般来说,我找不到为不同路径添加不同 CGContext 并将它们全部绘制在 DrawRect 中的好方法 完全可以在 -drawRect: 内的单个 CGContext 中绘制多条具有不同笔触颜色的线条。您可能想重新表述您的问题,并包含有关您如何尝试做事的更多详细信息。 (提示:每次调用 -drawRect: 时,您都是从头开始——您不能在上次绘制的内容之上绘制或擦除它。如果您想绘制多个路径或颜色,您需要保留多个 pathlineColor 值。) 感谢您的帮助和提示。我已经用我遇到的主要问题更新了问题 【参考方案1】:

您想分别描边每条路径,如下所示:

override func drawRect(rect: CGRect) 
    let context : CGContextRef = UIGraphicsGetCurrentContext()

    // Set parameters in the context that are the same for all lines
    CGContextSetLineCap(context, kCGLineCapRound)
    CGContextSetAlpha(context, lineOpacity)

    for line in pathArray 
        // Set parameters in the context that are specific to this line
        CGContextSetLineWidth(context, line.structLineWidth)
        CGContextSetStrokeColorWithColor(context, line.structLineColor.CGColor)

        // Add the line's path to the context's current path:
        CGContextAddPath(context, line.structPath)
        // And stroke it.
        CGContextStrokePath(context)
        // (This has the side effect of clearing the context's current path.)
    

CGContext 跟踪当前路径。将其视为您无法直接访问的CGMutablePath。您可以通过调用 CGContextAddPath 或许多其他函数来影响它。

CGContext 的当前路径实际上是不可见的,直到您通过调用 CGContextStrokePath 之类的函数来告诉上下文绘制它。那时,上下文使用当前路径和上下文中的其他值(描边颜色、alpha、线宽等)来确定要绘制的内容,并绘制出来。

您的代码将每一行的路径添加到当前路径中,因此您最终得到了包含多个断开连接的子路径的当前路径。然后你在最后调用了一次CGContextStrokePath,所有这些子路径都是使用你最近设置的参数值绘制的。所以你只看到了最后一行的宽度和颜色。

【讨论】:

感谢您抽出时间库尔特。这很有意义,并解决了我遇到的问题。它产生了一种意想不到的副作用,即在路径相遇的地方再次绘制所有端点,当不透明度设置为 1 以外的值时,这是可见的。这是清理上下文当前路径的副作用吗? Link 那是因为每条线的路径的末端重叠,所以你在彼此之上绘制两个东西,结果更暗。要解决这个问题,您可以在所有线条的绘图周围使用transparency layer,或者您可以设置视图的alpha 而不是绘图的alpha。后者几乎可以肯定更快,但灵活性较差。 @KurtRevis 你能帮我解决我的drawRect问题吗? ***.com/questions/39855349/…

以上是关于覆盖绘图应用程序的drawRect的主要内容,如果未能解决你的问题,请参考以下文章

在我的自定义 UIView 中,设置子视图的 backgroundColor 会导致它覆盖我的 drawRect 绘图(CGContextRef、CGMutablePathRef 等)。怎么修?

在 drawRect 上添加覆盖图像

如何使用 drawRect 覆盖在 UIView 子类的某些区域中获得透明度

UIView 实时强制重绘(绘图应用)

没有子类化的重载方法(特别是drawRect:)

使用 NSView 进行图层支持的绘图时没有调用 drawRect