问题描述:


Note: In the below question, I use the term 'lagging' when I probably mean 'latency' when drawing using the addCurveToPoint function.


Problem:

Both bezier curve functions, addQuadCurveToPoint and addCurveToPoint have one strength and one weakness each. The aim is to get the perfect combination of both, a perfect continuous smooth curved line that is lag-free when drawn. The images below show where the touch on the screen typically is in comparison to the updated drawing.

The below image uses the function addQuadCurveToPoint. It draws fast

with no lagging while drawing during touch events, but the end result is a

less perfect smooth curved line that appears more segmented.

The below image uses the function

addCurveToPoint. It draws near perfect continuous smooth curved

lines but is slower with some lag noticeable while drawing during

touch events.


Question:

Can anyone help explain or give a solution please:

  1. how to get perfect addQuadCurveToPoint curved lines or lag-free addCurveToPoint curved lines?


Note: The focus of this question is immediate lagging from the initial touch event for addCurveToPoint, not lagging over time, and also the less perfect curve line for addQuadCurveToPoint.


This code example is just one type of many implementations of 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()

}

}


This code example is just one type of many implementations of 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)

}

}

相关阅读:
Top