nameless
nameless

Reputation: 157

How to prevent CGContext strokePath or drawPath line drawings from floating up/spinning back?

Using Swift to draw lines, it keeps moving up the longer I continue to draw. Or maybe it's rotating back, like it's on a ball? The pictures show me starting out with a line, then as I draw, you can see that it reaches the top of the square. It's so weird! Why is that happening? How can I stop it? Code below.

Drawing Start

Drawing End

var context: CGContext?
var adjustedImageViewRect: CGRect?
var adjustedImageView: UIImageView?

var lastPoint = CGPoint.zero
var firstPoint = CGPoint.zero
var brushWidth: CGFloat = 10.0
var opacity: CGFloat = 1.0
var swiped = false

var undermineArray: [CGPoint] = []

@IBOutlet weak var drawLineImageView: UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()
    drawLineImageView.image = UIImage(named: "layer")
}

override func viewDidAppear(_ animated: Bool) {
    let rect = AVMakeRect(aspectRatio: drawLineImageView.image!.size, insideRect: drawLineImageView.bounds)
    adjustedImageViewRect = rect

    adjustedImageView = UIImageView(frame: rect)
    self.view.addSubview(adjustedImageView!)
    self.view.bringSubview(toFront: adjustedImageView!)
}

func drawLine(from fromPoint: CGPoint, to toPoint: CGPoint) {

    if let adjImgView = adjustedImageView {
        if let adjImgViewRect = adjustedImageViewRect {

            UIGraphicsBeginImageContextWithOptions(adjImgViewRect.size, false, 0)

            adjImgView.image?.draw(in: adjImgView.bounds)

            context = UIGraphicsGetCurrentContext()
            context?.move(to: fromPoint)
            context?.addLine(to: toPoint)
            context?.setLineCap(CGLineCap.round)
            context?.setLineWidth(brushWidth)
            context?.setStrokeColor(UIColor.red.cgColor)
            context?.setBlendMode(CGBlendMode.normal)
            context?.strokePath()

            adjImgView.image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
        }
    }
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    //clear out previous line
    firstPoint = CGPoint.zero
    lastPoint = CGPoint.zero
    undermineArray.removeAll()

    adjustedImageView?.image = UIImage()
    swiped = false
    if let touch = touches.first {
        if let rect = adjustedImageViewRect {
            if (touch.location(in: self.adjustedImageView).y < 0
                || touch.location(in: self.adjustedImageView).y > rect.height) {
                adjustedImageView?.image = UIImage()
                return
            }
        }
        firstPoint = touch.location(in: self.adjustedImageView)
        lastPoint = touch.location(in: self.adjustedImageView)
        undermineArray.append(firstPoint)
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    swiped = true
    if let touch = touches.first {

        var currentPoint = touch.location(in: adjustedImageView)
        if let rect = adjustedImageViewRect {
            if (touch.location(in: self.adjustedImageView).y < 0) {
                currentPoint.y = 0
            }

            if (touch.location(in: self.adjustedImageView).y > rect.height) {
                currentPoint.y = rect.height
            }
        }

        undermineArray.append(currentPoint)
        drawLine(from: lastPoint, to: currentPoint)
        lastPoint = currentPoint
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

    if let rect = adjustedImageViewRect {
        if (firstPoint.y < 0 || firstPoint.y > rect.height) {
            adjustedImageView?.image = UIImage()
            return
        }
    }

    if let touch = touches.first {
        if let rect = adjustedImageViewRect {
            if (touch.location(in: self.adjustedImageView).y < 0) {
                lastPoint.y = 0
            }
            if (touch.location(in: self.adjustedImageView).y > rect.height) {
                lastPoint.y = rect.height
            }
        }
    }

    if !swiped {
        self.drawLine(from: lastPoint, to: lastPoint)
    }
}

Upvotes: 1

Views: 388

Answers (1)

nameless
nameless

Reputation: 157

AH I got it. It turns out that UIImage's draw() function draws the image, and unbeknownst to me until now, "scales it as needed to fit."

So, we'll use something else. We'll just use drawAsPattern().

Change

adjImgView.image?.draw(in: adjImgView.bounds)

to

adjImgView.image?.drawAsPattern(in: adjImgView.bounds)

and voilà, no crazy scaling/spinning/shrinking going on.

Upvotes: 3

Related Questions