绘制曲线没有滞后?

Posted

技术标签:

【中文标题】绘制曲线没有滞后?【英文标题】:Drawing curved lines without lagging? 【发布时间】:2015-11-04 16:44:57 【问题描述】:

我有一个下面的类,当用户触摸他们的设备时,当附加到视图时会绘制曲线。问题是绘制的线条似乎比手指在屏幕上的位置滞后。当新的线路部分显示在距离触摸屏幕的手指一小段距离时,这种滞后足以引起人们的注意和轻微的烦人。

代码使用addCurveToPoint曲线方法。 (替代的addQuadCurveToPoint 曲线方法在质量曲线方面似乎不太优越,但在屏幕上显示速度更快。)

我怀疑这个问题与 setNeedsDisplay 被调用一次 counter == 4 时有关。在绘制曲线之前,代码似乎要等到在绘制时收到 4 个新的触摸点。理想情况下,在每个触摸点(即计数器 == 1)绘制一条曲线,消除滞后。 (更改 Counter == 1 似乎不起作用。)

我迷路了,不知道如何更新代码以进一步改进它以消除短暂的滞后但保留曲线。 需要对以下代码进行哪些更改才能消除短暂的延迟?

// Swift 2 code below tested using Xcode 7.0.1.

class drawView: UIView 

var path:UIBezierPath?
var incrementalImage:UIImage?

var points = [CGPoint?](count: 5, repeatedValue: nil)
var counter:Int?

var infoView:UIView = UIView()
var strokeColor:UIColor?


required init?(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)
    self.multipleTouchEnabled = false
    self.backgroundColor = UIColor.whiteColor()
    path = UIBezierPath()
    path?.lineWidth = 20.0
    strokeColor = UIColor.darkGrayColor()
    path?.lineCapStyle = CGLineCap.Round


override init(frame: CGRect) 
    super.init(frame: frame)
    self.multipleTouchEnabled = false
    path = UIBezierPath()
    path?.lineWidth = 20.0



override func drawRect(rect: CGRect) 
    incrementalImage?.drawInRect(rect)
    strokeColor?.setStroke()
    path?.stroke()


override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) 
    counter = 0
    let touch: AnyObject? = touches.first
    points[0] = touch!.locationInView(self)
    infoView.removeFromSuperview()


override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) 
    let touch: AnyObject? = touches.first
    let point = touch!.locationInView(self)
    counter = counter! + 1
    points[counter!] = point

    if counter == 4

        points[3]! = CGPointMake((points[2]!.x + points[4]!.x)/2.0, (points[2]!.y + points[4]!.y)/2.0)
        path?.moveToPoint(points[0]!)
        path?.addCurveToPoint(points[3]!, controlPoint1: points[1]!, controlPoint2: points[2]!)

        self.setNeedsDisplay()

        points[0]! = points[3]!
        points[1]! = points[4]!
        counter = 1

    


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

    self.drawBitmap()
    self.setNeedsDisplay()
    path?.removeAllPoints()
    counter = 0


override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) 
    self.touchesEnded(touches!, withEvent: event)


func drawBitmap()
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, 0.0)
        strokeColor?.setStroke()
        if((incrementalImage) == nil)
            let rectPath:UIBezierPath = UIBezierPath(rect: self.bounds)
            UIColor.whiteColor().setFill()
            rectPath.fill()
        

        incrementalImage?.drawAtPoint(CGPointZero)
        path?.stroke()
        incrementalImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()


【问题讨论】:

【参考方案1】:

首先,我相信你做错了。如果您想通过用户输入而不是通过用户输入来绘制几条线,而是为圆圈、波浪线、简单的东西绘制几条线,这通常效果很好。

使用时:

self.setNeedsDisplay()

您每次都在重绘所有线条!这是一个艰难的CPU,这就是为什么你有一个滞后。图像用户画了几百条线,然后变成了一千条线,每次他/她触摸屏幕时,它都会重新绘制所有这些线。

好的。所以,我建议做的是有 2 个 UIImageViews: 1) mainImageView - 它将保存整个绘图。 2) tempImageView - 用户将使用它来绘制。

当用户在“tempImageView”上触摸/绘图时,它会一直绘制直到他们松开屏幕,然后将“tempImageView”合并到“mainImageView”

这里有一个教程:

http://www.raywenderlich.com/87899/make-simple-drawing-app-uikit-swift

【讨论】:

感谢您的回复。我不认为这是原因。在绘图时进行更改时调用 setNeedsDisplay 非常有效。一个很好的解释是:***.com/a/10818417 实际上你提到的示例教程是我最初开始使用的,但它在 CPU 上要困难得多。它确实在不应该的 touches 事件中绘制。事实上,示例教程中的方法,CPU 已达到极限,应用程序在旧设备上崩溃。上面代码中的短暂延迟始于第一次接触。只是想弄清楚如何改善这种情况。干杯

以上是关于绘制曲线没有滞后?的主要内容,如果未能解决你的问题,请参考以下文章

如何提取plot绘制出的曲线上的各点坐标并存入数组

GLSL片段着色器 - 绘制简单的粗曲线

在Python中绘制累积增益曲线(ModuleNotFoundError:没有名为'scikitplot'的模块)

贝塞尔曲线开发的艺术

贝塞尔曲线开发的艺术

PR曲线,ROC曲线以及绘制,AUC