Как включить несколько касаний и нарисовать две линии одновременно?

Код, который запускается под управлением среды выполнения общего языка (CLR), известен как управляемый код. Код, который не запускается в среде CLR, известен как собственный код.

0
задан rmaddy 19 March 2019 в 14:42
поделиться

2 ответа

То, что вы сделали, это непосредственно для рисования одной линии. Вы используете первое касание в своих методах touch, а также у вас есть только одна «текущая строка».

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

class Line {
    var start: CGPoint = .zero
    var end: CGPoint = .zero
}

private var finishedLines: [Line] = [Line]()
private var currentLines: [UITouch: Line] = [UITouch: Line]()

private func insertNewPoint(_ point: CGPoint, forTouch touch: UITouch) {
    if let line = currentLines[touch] {
        line.end = point
    } else {
        currentLines[touch] = {
            let newLine = Line()
            newLine.start = point
            return newLine
        }()
    }
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    touches.forEach { touch in
        insertNewPoint(touch.location(in: self.view), forTouch: touch)
    }
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesMoved(touches, with: event)
    touches.forEach { touch in
        insertNewPoint(touch.location(in: self.view), forTouch: touch)
    }
}

private func finishLine(at point: CGPoint, forTouch touch: UITouch) {
    guard let line = currentLines[touch] else { return }
    currentLines[touch] = nil
    line.end = point
    self.finishedLines.append(line)
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesEnded(touches, with: event)
    touches.forEach { touch in
        finishLine(at: touch.location(in: self.view), forTouch: touch)
    }
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesCancelled(touches, with: event)
    touches.forEach { touch in
        finishLine(at: touch.location(in: self.view), forTouch: touch)
    }
}

Так что, где вы обрабатываете прикосновения, наиболее важно перебрать все из них touches.forEach { touch in. И вам нужен набор строк, которые в вашем случае должны быть назначены на штрихи. Он должен работать с использованием словаря [UITouch: Line].

Полный пример:

import UIKit

class ViewController: UIViewController {

    private var finishedLines: [Line] = [Line]()
    private var currentLines: [UITouch: Line] = [UITouch: Line]()

    private var lineView: LineView?

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.isMultipleTouchEnabled = true
        self.lineView = {
            let view = LineView(frame: self.view.bounds)
            view.isUserInteractionEnabled = false
            self.view.addSubview(view)
            return view
        }()
    }

    private func updateDrawing() {
        lineView?.lines = finishedLines + currentLines.map { [111].value }
        lineView?.setNeedsDisplay()
    }

    private func insertNewPoint(_ point: CGPoint, forTouch touch: UITouch) {
        if let line = currentLines[touch] {
            line.end = point
        } else {
            currentLines[touch] = {
                let newLine = Line()
                newLine.start = point
                return newLine
            }()
        }
        updateDrawing()
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        touches.forEach { touch in
            insertNewPoint(touch.location(in: self.view), forTouch: touch)
        }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        touches.forEach { touch in
            insertNewPoint(touch.location(in: self.view), forTouch: touch)
        }
    }

    private func finishLine(at point: CGPoint, forTouch touch: UITouch) {
        guard let line = currentLines[touch] else { return }
        currentLines[touch] = nil
        line.end = point
        self.finishedLines.append(line)
        updateDrawing()
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        touches.forEach { touch in
            finishLine(at: touch.location(in: self.view), forTouch: touch)
        }
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesCancelled(touches, with: event)
        touches.forEach { touch in
            finishLine(at: touch.location(in: self.view), forTouch: touch)
        }
    }


}

// MARK: - Line

extension ViewController {

    class Line {
        var start: CGPoint?
        var end: CGPoint?
    }

}

// MARK: - LineView

extension ViewController {

    class LineView: UIView {

        var lines: [Line]?

        override func draw(_ rect: CGRect) {
            super.draw(rect)

            // Fill white background
            UIColor.white.setFill()
            UIBezierPath(rect: rect).fill()

            // Draw all lines
            UIColor.red.setStroke()
            lines?.forEach { line in
                if let start = line.start, let end = line.end {
                    let path = UIBezierPath()
                    path.move(to: start)
                    path.addLine(to: end)
                    path.stroke()
                }
            }
        }

    }

}

Вы можете вставить этот код во вновь созданный проект Xcode iOS в свой ViewController, и он должен работать.

0
ответ дан Matic Oblak 19 March 2019 в 14:42
поделиться

Каждый из touchesBegan..., touchesMoved..., touchesEnded..., touchesCancelled... имеет набор касаний в качестве входного параметра. Система гарантирует, что у каждого пальца одинаковые UITouch от начала до конца / отменены.
Прямо сейчас вы обрабатываете только один палец, используя touches.first. Вместо этого вам нужно нарисовать отдельную линию для каждого прикосновения. Что-то вроде:

  override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        touches.forEach { touch in
            line[touch]?.end = touch.location(in: self)
        }
        setNeedsDisplay()
    }
0
ответ дан ManWithBear 19 March 2019 в 14:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: