Рисование линий идеального округления, Swift - PullRequest
3 голосов
/ 28 октября 2019

Я работаю над прототипом приложения для рисования, и я хочу достичь идеальных линий округления. Я реализовал рисование с помощью кривых, но все же мои линии выглядят немного пиксельными.

Вот мой результат:

enter image description here

и вот что я пытаюсь достичь:

enter image description here

    class ViewController: UIViewController {
        private var currentPoint: CGPoint?
        private var previousPoint1: CGPoint?
        private var previousPoint2: CGPoint?
        private var lineColor = UIColor.black
        private var lineWidth = CGFloat(10)
        private var lineAlpha = CGFloat(1)
        @IBOutlet private weak var imageView: UIImageView!

        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            guard let touch = touches.first else { return }

            previousPoint1 = touch.previousLocation(in: self.view)
            currentPoint = touch.location(in: self.view)
        }

        override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
            guard let touch = touches.first else { return }

            previousPoint2 = previousPoint1
            previousPoint1 = touch.previousLocation(in: self.view)
            currentPoint = touch.location(in: self.view)

            let mid1 = middlePoint(previousPoint1!, previousPoint2: previousPoint2!)
            let mid2 = middlePoint(currentPoint!, previousPoint2: previousPoint1!)

            draw(move: CGPoint(x: mid1.x, y: mid1.y), to: CGPoint(x: mid2.x, y: mid2.y), control: CGPoint(x: previousPoint1!.x, y: previousPoint1!.y))
        }

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

        private func middlePoint(_ previousPoint1: CGPoint, previousPoint2: CGPoint) -> CGPoint {
            return CGPoint(x: (previousPoint1.x + previousPoint2.x) * 0.5, y: (previousPoint1.y + previousPoint2.y) * 0.5)
        }

        func draw(move: CGPoint, to: CGPoint, control: CGPoint) {
            UIGraphicsBeginImageContext(view.frame.size)
            guard let ctx = UIGraphicsGetCurrentContext() else { return }
            imageView.image?.draw(in: view.bounds)
            ctx.move(to: move)
            ctx.addQuadCurve(to: to, control: control)
            ctx.setLineCap(.round)
            ctx.setLineJoin(.round)
            ctx.setLineWidth(lineWidth)
            ctx.setStrokeColor(lineColor.cgColor)
            ctx.setBlendMode(.normal)
            ctx.setAlpha(lineAlpha)
            ctx.strokePath()
            let finalImage = UIGraphicsGetImageFromCurrentImageContext()
            imageView.image = finalImage
            UIGraphicsEndImageContext()
        }
    }

PS Я хочу рисовать через контекст, не используя drawRect

1 Ответ

2 голосов
/ 03 ноября 2019

Проблема здесь в том, что масштаб создаваемого вами imageContext неверен. Вместо того чтобы создавать свой контекст с помощью UIGraphicsBeginImageContext , попробуйте создать его с помощью UIGraphicsBeginImageContextWithOptions и задать значение масштаба равным 0. Когда вы задаете значение масштаба 0, коэффициент масштабирования устанавливается равным коэффициенту масштабированияглавного экрана устройства. Обновленный фрагмент кода будет выглядеть следующим образом.

func draw(move: CGPoint, to: CGPoint, control: CGPoint) {
        UIGraphicsBeginImageContextWithOptions(view.frame.size, false, 0)
        guard let ctx = UIGraphicsGetCurrentContext() else { return }
        imageView.image?.draw(in: view.bounds)
        ctx.move(to: move)
        ctx.addQuadCurve(to: to, control: control)
        ctx.setLineCap(.round)
        ctx.setLineJoin(.round)
        ctx.setLineWidth(lineWidth)
        ctx.setStrokeColor(lineColor.cgColor)
        ctx.setBlendMode(.normal)
        ctx.setAlpha(lineAlpha)
        ctx.strokePath()
        let finalImage = UIGraphicsGetImageFromCurrentImageContext()
        imageView.image = finalImage
        UIGraphicsEndImageContext()
    }
...