簡體   English   中英

畫一條帶有起始接觸點的直線

[英]draw a straight line with a starting touch point

我希望我的 swift 代碼繪制一條直線。 現在它選擇一個點,用戶擴展錨定在第一個點的線。 我只希望用戶能夠向左或向右畫線。 我嘗試交替 bezier.addLine(to: CGPoint(x:startTouch!.x, y:startTouch!.y)) 但這似乎沒有任何效果。

import UIKit

class ViewController2: UIViewController {

    @IBOutlet weak var drawingPlace: UIImageView!

    var startTouch : CGPoint?
    var secondTouch : CGPoint?
    var currentContext : CGContext?
    var prevImage : UIImage?


    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemOrange
        drawingPlace.backgroundColor = .gray
    }


    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        startTouch = touch?.location(in: drawingPlace)
    }

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

        for touch in touches{
            secondTouch = touch.location(in: drawingPlace)

            if(self.currentContext == nil){
                UIGraphicsBeginImageContext(drawingPlace.frame.size)
                self.currentContext = UIGraphicsGetCurrentContext()
            }else{
                self.currentContext?.clear(CGRect(x: 0, y: 0, width: drawingPlace.frame.width, height: drawingPlace.frame.height))
            }

            self.prevImage?.draw(in: self.drawingPlace.bounds)

            let bezier = UIBezierPath()

            bezier.move(to: startTouch!)
            bezier.addLine(to: secondTouch!)
            
            bezier.addLine(to: CGPoint(x:startTouch!.x, y:startTouch!.y))
            bezier.close()

            UIColor.blue.set()

            self.currentContext?.setLineWidth(4)
            self.currentContext?.addPath(bezier.cgPath)
            self.currentContext?.strokePath()
            let img2 = self.currentContext?.makeImage()
            drawingPlace.image = UIImage.init(cgImage: img2!)

        }
    }


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

        self.currentContext = nil
        self.prevImage = self.drawingPlace.image
    }

}

如果要繪制水平線,請創建一個CGPointx是觸摸的位置, y是起點的位置。 這將導致一條水平線。


話雖如此,以下是其他一些觀察結果:

  1. 如果您調用UIGraphicsBeginImageContext ,則必須調用UIGraphicsEndImageContext 您應該在touchesMoved執行此操作,而不是嘗試在此調用之外繼續使用上下文。

  2. 如果你要這樣做,我們現在通常會使用UIGraphicsImageRenderer

  3. 就個人而言,我不會嘗試為每次觸摸渲染圖像。 這是一個相當昂貴的操作。 我只會添加一個CAShapeLayer ,然后更新該層的path CAShapeLayer負責路徑的渲染。

  4. 我不太確定您為什么要遍歷觸摸數組。 我只想抓住一個並使用它。

  5. 我可能會建議使用預測性觸摸來最大程度地減少感知滯后。

  6. startTouch實際上是一個CGPoint ,而不是UITouch ,所以我可能會稱它為startPoint

  7. 如果你想制作快照圖像,我會在touchesEnded做,而不是在touchesMoved

例如:

class ViewController: UIViewController {
    @IBOutlet weak var imageView: UIImageView!
    
    var startPoint: CGPoint?

    let shapeLayer: CAShapeLayer = {
        let shapeLayer = CAShapeLayer()
        shapeLayer.lineWidth = 4
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.strokeColor = UIColor.blue.cgColor
        return shapeLayer
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        imageView.backgroundColor = .systemOrange
        imageView.layer.addSublayer(shapeLayer)
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        let touch = touches.first
        startPoint = touch?.location(in: imageView)
    }

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

        if let predicted = event?.predictedTouches(for: touch)?.last {
            touch = predicted
        }

        updatePath(in: imageView, to: touch)
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        updatePath(in: imageView, to: touch)
        let image = UIGraphicsImageRenderer(bounds: imageView.bounds).image { _ in
            imageView.drawHierarchy(in: imageView.bounds, afterScreenUpdates: true)
        }
        shapeLayer.path = nil
        imageView.image = image
    }
}

private extension ViewController {
    func updatePath(in view: UIView, to touch: UITouch) {
        let point = touch.location(in: view)
        guard view.bounds.contains(point) else { return }

        let bezier = UIBezierPath()

        bezier.move(to: startPoint!)
        bezier.addLine(to: CGPoint(x: point.x, y: startPoint!.y))

        shapeLayer.path = bezier.cgPath
    }
}

這只是將當前行渲染為CAShapeLayer ,但是當筆畫完成時,它會創建圖像視圖的快照(永久捕獲圖像中的筆畫),刪除形狀圖層的路徑,並更新圖像視圖的image

但希望這能回答有關如何使線條水平的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM