使用Core Graphics在UIImageView上绘制矩形 [英] Drawing a rectangle on UIImageView using Core Graphics

查看:132
本文介绍了使用Core Graphics在UIImageView上绘制矩形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让用户在 UIImageView 上绘制一个矩形
我为最后一个触摸位置添加了两个变量
我添加了此功能:-

I want to let the User to draw a rectangle on UIImageView I added two variables for first an last touch locations I added this function:-

func draw(from: CGPoint, to: CGPoint) {
    UIGraphicsBeginImageContext(imageView.frame.size)
    context = UIGraphicsGetCurrentContext()
    context?.setStrokeColor(UIColor(red: 0, green: 0, blue: 0, alpha: 1.0).cgColor)
    context?.setLineWidth(5.0)
    let currentRect = CGRect(x: from.x,
                             y: from.y,
                             width: to.x - from.x,
                             height: to.y - from.y)
    context?.addRect(currentRect)
    context?.drawPath(using: .stroke)
    context?.strokePath()
    imageView.image?.draw(in: self.imageView.frame)
    imageView.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}

我添加了方法od到( touchMoved )会绘制许多矩形

I add the method to (touchMoved) it draws many rectangles

我将方法添加到( touchEnded )绘制一个,但当用户移动触摸时不会显示

I add the method to (touchEnded) it draws one, but it does not appear when the user move the touch

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

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        lastTouchLocation = touch.location(in: self.view)
        draw(from: firstTouchLocation, to: lastTouchLocation)
    }
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    if let touch = touches.first {
        lastTouchLocation = touch.location(in: self.view)
        draw(from: firstTouchLocation, to: lastTouchLocation)
    }
}

我想让用户在 touchMoved 时扩展矩形,在 touchEnded

I want to let the user extend the rectangle when touchMoved and draw when the touchEnded.

推荐答案

您要替换的图片,其中的新图像由先前的图像加上在其上绘制的矩形组成。而不是从图像视图绘制图像,而是绘制原始图像。

You are replacing your image with a new image composed of the previous image plus a rectangle drawn over it. Rather than drawing the image from the image view, draw the original image.

或者,您可以将矩形渲染为形状图层,然后更新该形状图层的路径:

Alternatively, you could render the the rectangle as a shape layer and just update that shape layer's path:

class ViewController: UIViewController {

    @IBOutlet weak var imageView: UIImageView!

    private let shapeLayer: CAShapeLayer = {
        let _shapeLayer = CAShapeLayer()
        _shapeLayer.fillColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 0).cgColor
        _shapeLayer.strokeColor = #colorLiteral(red: 0, green: 0, blue: 0, alpha: 1).cgColor
        _shapeLayer.lineWidth = 3
        return _shapeLayer
    }()

    private var startPoint: CGPoint!

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.layer.addSublayer(shapeLayer)
    }

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

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

        let point: CGPoint

        if let predictedTouch = event?.predictedTouches(for: touch)?.last {
            point = predictedTouch.location(in: imageView)
        } else {
            point = touch.location(in: imageView)
        }

        updatePath(from: startPoint, to: point)
    }

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

        let point = touch.location(in: imageView)

        updatePath(from: startPoint, to: point)
        imageView.image = imageView.snapshot(afterScreenUpdates: true)
        shapeLayer.path = nil
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        shapeLayer.path = nil
    }

    private func updatePath(from startPoint: CGPoint, to point: CGPoint) {
        let size = CGSize(width: point.x - startPoint.x, height: point.y - startPoint.y)
        let rect = CGRect(origin: startPoint, size: size)
        shapeLayer.path = UIBezierPath(rect: rect).cgPath
    }

}

其中:

extension UIView {
    func snapshot(afterScreenUpdates: Bool = false) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(bounds.size, isOpaque, 0)
        drawHierarchy(in: bounds, afterScreenUpdates: afterScreenUpdates)
        let image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }
}

这不仅更简单,而且也更加有效。

This is not only simpler, but more efficient, too.

结果如下:

顺便说一句,我可能建议在 touchesMoved 中使用预测性触摸。在可以产生响应更快的UI的设备(不是模拟器)上。

By the way, I might suggest using predictive touches in touchesMoved. On a device (not the simulator) that can yield a slightly more responsive UI.

这篇关于使用Core Graphics在UIImageView上绘制矩形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆