ios - 如何快速在 UIImage 上绘制/涂鸦线?

标签 ios swift uiimage

enter image description here

我需要在 UIImage 中绘制/涂鸦一条线,如上图,我看到很多教程在 UIView 上涂鸦线,但在 UIImage 中没有。

用户在图像上涂鸦后,我想将其保存为新图像(有线条的图像)。我如何在 Swift 中做到这一点?

我只能在 UIView 上找到画线,而不是在 UIImage 上 在 UIView 上绘图就像这个 youtube 教程中的这个一样 http://youtube.com/watch?v=gbFHqHHApC4 ,我改成继承DrawView到UIImageView

   struct  Stroke {
    let startPoint : CGPoint
    let endPoint : CGPoint
    let strokeColor : CGColor
}


class DrawView : UIImageView {

    var isDrawing = false
    var lastPoint : CGPoint!
    var strokeColor : CGColor! = UIColor.black.cgColor
    var strokes = [Stroke]()


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

        guard !isDrawing else { return }
        isDrawing = true

        guard let touch = touches.first else {return}
        let currentPoint = touch.location(in: self)
        lastPoint = currentPoint
        print(currentPoint)


    }



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

        guard isDrawing else { return}

        guard let touch = touches.first else {return}
        let currentPoint = touch.location(in: self)
        let stroke = Stroke(startPoint: lastPoint, endPoint: currentPoint, strokeColor: strokeColor)
        strokes.append(stroke)
        lastPoint = currentPoint

        setNeedsDisplay()


        print(currentPoint)
    }




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

        guard isDrawing else { return}
        isDrawing = false


        guard let touch = touches.first else {return}

        let currentPoint = touch.location(in: self)
        let stroke = Stroke(startPoint: lastPoint, endPoint: currentPoint, strokeColor: strokeColor)
        strokes.append(stroke)

        setNeedsDisplay()

        lastPoint = nil
        print(currentPoint)

    }


    override func draw(_ rect: CGRect) {

        let context = UIGraphicsGetCurrentContext()
        context?.setLineWidth(5)
        context?.setLineCap(.round)

        for stroke in strokes {
            context?.beginPath()

            context?.move(to: stroke.startPoint)
            context?.addLine(to: stroke.endPoint)

            context?.setStrokeColor(stroke.strokeColor)
            context?.strokePath()
        }

    }


    func erase() {
        strokes = []
        strokeColor = UIColor.black.cgColor
        setNeedsDisplay()
    }






}

我已将 Storyboard中的 UIImage 分配为使用自定义类“DrawView”,就像我上面的代码一样,但我不知道为什么这些线条没有出现在我的 UIImage 上

最佳答案

详情

  • Xcode 10.2.1 (10E1001)、Swift 5

解决方案

import UIKit

// https://stackoverflow.com/a/41009006/4488252
class DrawnImageView: UIImageView {
    private lazy var path = UIBezierPath()
    private lazy var previousTouchPoint = CGPoint.zero
    private lazy var shapeLayer = CAShapeLayer()

    override func awakeFromNib() {
        super.awakeFromNib()
        setupView()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    func setupView(){
        layer.addSublayer(shapeLayer)
        shapeLayer.lineWidth = 4
        shapeLayer.strokeColor = UIColor.white.cgColor
        isUserInteractionEnabled = true
    }

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        if let location = touches.first?.location(in: self) { previousTouchPoint = location }
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesMoved(touches, with: event)
        if let location = touches.first?.location(in: self) {
            path.move(to: location)
            path.addLine(to: previousTouchPoint)
            previousTouchPoint = location
            shapeLayer.path = path.cgPath
        }
    }
}

// https://stackoverflow.com/a/40953026/4488252
extension UIView {
    var screenShot: UIImage?  {
        let scale = UIScreen.main.scale
        UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale)
        if let context = UIGraphicsGetCurrentContext() {
            layer.render(in: context)
            let screenshot = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return screenshot
        }
        return nil
    }
}

用法

  1. 将 DrawnImageView 添加到您的根(父) View (将自动启用触摸绘图)
  2. 要保存 UIImage 使用 drawingImageView.screenShot

完整样本

Do not forget to add the solution code here

import UIKit

class ViewController: UIViewController {

    fileprivate weak var savedImageView: UIImageView?
    fileprivate weak var drawnImageView: UIImageView?

    override func viewDidLoad() {
        super.viewDidLoad()

        let drawnImageView = addImageView(image: UIImage(named: "swift")) as DrawnImageView
        drawnImageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        drawnImageView.heightAnchor.constraint(equalToConstant: UIScreen.main.bounds.height/3).isActive = true
        self.drawnImageView = drawnImageView

        let button = UIButton()
        button.setTitle("Save Image", for: .normal)
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitleColor(.blue, for: .normal)
        view.addSubview(button)
        button.topAnchor.constraint(equalTo: drawnImageView.bottomAnchor, constant: 60).isActive = true
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.heightAnchor.constraint(equalToConstant: 44).isActive = true
        button.addTarget(self, action: #selector(saveImageButtonTouchUpInside), for: .touchUpInside)

        let savedImageView = addImageView()
        savedImageView.topAnchor.constraint(equalTo: button.bottomAnchor, constant: 60).isActive = true
        savedImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
        self.savedImageView = savedImageView
    }

    private func addImageView<T: UIImageView>(image: UIImage? = nil) -> T {
        let imageView = T(frame: .zero)
        imageView.contentMode = .scaleAspectFit
        imageView.image = image
        view.addSubview(imageView)

        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
        return imageView
    }

    @objc func saveImageButtonTouchUpInside(sender: UIButton) {
        savedImageView?.image = drawnImageView?.screenShot
    }
}

结果

enter image description here enter image description here

关于ios - 如何快速在 UIImage 上绘制/涂鸦线?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49919853/

相关文章:

ios - Swift URLSession.shared.dataTask GET 请求-1001 返回超时

swift - 将 SKSpriteNode 转换为 UIImage

ios - 带有分页和缩放的 UIImage 或 UIImageView 单击

iOS:如何在 .aif 录音的开始和结束时修剪静音?

ios - 安排通知从下周开始每天执行

ios - Swift 私有(private)访问控制导致问题

iphone - 崩溃: UIImage style crash with code for iOS 6?

ios - 获取有关 DEFINES_Modules 依赖分析的警告

ios - 应用转换并设置新的键入属性后,UITextView 被裁剪

ios - 使用未解析的标识符 PFFacebookUtils