addCurveToPoint和addQuadCurveToPoint之间的差异在Swift中绘制了平滑的曲线

时间:2015-11-05 07:38:02

标签: ios swift optimization drawing uibezierpath

注意:在下面的问题中,我使用术语“落后”'当我可能意味着延迟'使用addCurveToPoint函数绘图时。

问题:

贝塞尔曲线函数addQuadCurveToPointaddCurveToPoint都有一个强度和一个弱点。目的是将两者完美结合,形成完美连续的平滑曲线,绘制时无滞后曲线。下图显示了屏幕上的触摸通常与更新的图形相比的位置。

  

下图使用函数addQuadCurveToPoint。它吸引得很快   在触摸事件期间绘制时没有滞后,但最终结果是a   不太完美的平滑曲线,看起来更分割。

Drawing with addQuadCurveToPoint

  

下图使用该功能   addCurveToPoint。它绘制近乎完美的连续光滑曲线   在绘制期间,但是较慢但有些滞后   触摸事件。

enter image description here

问题:

任何人都可以帮忙解释或给出解决方案:

  1. 如何获得完美addQuadCurveToPoint曲线无滞后addCurveToPoint曲线?
  2. 注意:此问题的焦点是addCurveToPoint的初始触摸事件立即滞后,不会随着时间的推移而滞后,而addQuadCurveToPoint的曲线也不那么完美。

    此代码示例只是addCurveToPoint的许多实现中的一种类型:

    // 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()
    }
    }
    

    此代码示例只是addQuadCurveToPoint的许多实现中的一种类型:

    // Swift 2 code below tested using Xcode 7.0.1.
    
    class DrawableView: UIView {
    
        let path=UIBezierPath()
        var previousPoint:CGPoint
        var lineWidth:CGFloat=20.0
        // Only override drawRect: if you perform custom drawing.
        // An empty implementation adversely affects performance during animation.
        override init(frame: CGRect) {
            previousPoint=CGPoint.zero
            super.init(frame: frame)
        }
    
        required init?(coder aDecoder: NSCoder) {
            previousPoint=CGPoint.zero
            super.init(coder: aDecoder)
            let panGestureRecognizer=UIPanGestureRecognizer(target: self, action: "pan:")
            panGestureRecognizer.maximumNumberOfTouches=1
            self.addGestureRecognizer(panGestureRecognizer)
    
        }
    
        override func drawRect(rect: CGRect) {
            // Drawing code
            UIColor.darkGrayColor().setStroke()
            path.stroke()
            path.lineWidth=lineWidth
            path.lineCapStyle = .Round
        }
        func pan(panGestureRecognizer:UIPanGestureRecognizer)->Void
        {
            let currentPoint=panGestureRecognizer.locationInView(self)
            let midPoint=self.midPoint(previousPoint, p1: currentPoint)
    
            if panGestureRecognizer.state == .Began
            {
                path.moveToPoint(currentPoint)
            }
            else if panGestureRecognizer.state == .Changed
            {
                path.addQuadCurveToPoint(midPoint,controlPoint: previousPoint)
            }
    
            previousPoint=currentPoint
            self.setNeedsDisplay()
        }
        func midPoint(p0:CGPoint,p1:CGPoint)->CGPoint
        {
            let x=(p0.x+p1.x)/2
            let y=(p0.y+p1.y)/2
            return CGPoint(x: x, y: y)
        }
    
    }
    

0 个答案:

没有答案