【问题标题】:Drawing on UIImageView in swift快速在 UIImageView 上绘图
【发布时间】:2017-11-28 15:07:17
【问题描述】:

我正在尝试开发一个可以在 UIImageView 上绘制内容的应用程序。我有以下代码。

import UIKit
class Line
{
    var startPoint:CGPoint
    var endPoint:CGPoint

    init (start:CGPoint , end:CGPoint)
    {
        startPoint = start
        endPoint = end
    }
}


class AnnotationView: UIView {

    static internal let nibName = "AnnotationView"
    @IBOutlet weak var imageView: UIImageView!
    var lines :[Line] = []
    var lastPoint:CGPoint!


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

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        if let touch  = touches.first
        {
            let newPoint = touch.location(in:self)
            lines.append(Line(start: lastPoint, end: newPoint))
            lastPoint = newPoint
            self.setNeedsDisplay()
        }
    }
    override func draw(_ rect: CGRect) {
        if let context = UIGraphicsGetCurrentContext()
        {
            context.beginPath()
            for line in lines
            {
                context.move(to: line.startPoint)
                context.addLine(to: line.endPoint)
            }
            context.setLineCap(CGLineCap.round)
            context.setStrokeColor(red: 0, green: 0, blue: 0, alpha: 1)
            context.setLineWidth(5)
            context.strokePath()
        }
    }
}

所以现在在上面的代码中,我有一个派生自 UIView 的 AnnotationView 类,其中我有一个 UIImageView,我从界面构建器将其设置为超级视图的完整大小。这是一个简单的绘图应用程序,我想在 UIImageView 上绘制一些东西。现在的问题是当 imageView.image 为 nil 时,它会显示我的绘图,如果为 imageView.image 设置了任何图像,那么它不会显示绘图。它只显示在此 imageView 中设置的图像。我在这两种情况下都调试了所有方法都被调用。肯定有我想念的东西。谁能帮帮我吗?我想在我在 UIImageView 中设置的图像上显示我的绘图。 问候, 尼娜

【问题讨论】:

    标签: swift uiimageview drawing core-graphics drawrect


    【解决方案1】:

    问题是您正在绘制AnnotationView 的主层,该层位于它的任何子视图后面,包括您的UIImageView。解决方案是将您的绘图移动到单独的sublayer 添加到AnnotationView 的主层。

    不是直接在draw() 方法中绘制线条,您需要为您的绘图叠加层设置一个单独的图层。将此属性添加到您的AnnotationView

    let drawingLayer = CAShapeLayer()
    

    并覆盖awakeFromNib(),以便在您的视图从 Storyboard/Nib 加载后立即使该层成为其他所有内容之上的子层:

    override func awakeFromNib() {
        super.awakeFromNib()
        layer.addSublayer(drawingLayer)
    }
    

    现在让我们创建一个函数,以便在您每次需要更新叠加层时调用,而不是调用 setNeedsDisplay()

    func updateDrawingOverlay() {
        let path = CGMutablePath()
    
        for line in lines {
            path.move(to: line.startPoint)
            path.addLine(to: line.endPoint)
        }
    
        drawingLayer.frame = imageView.frame
        drawingLayer.path = path
        drawingLayer.lineWidth = 5
        drawingLayer.strokeColor = UIColor.black.cgColor
    
        setNeedsDisplay()
    }
    

    删除draw(_:) 方法中的代码,因为它现在是多余的,并将来自touchesMoved(_: with:)setNeedsDisplay() 调用替换为updateDrawingOverlay() 调用。


    对你来说,整个事情应该是这样的:

    import UIKit
    
    class Line {
        var startPoint:CGPoint
        var endPoint:CGPoint
    
        init (start:CGPoint , end:CGPoint) {
            startPoint = start
            endPoint = end
        }
    }
    
    
    class AnnotationView: UIView {
        static internal let nibName = "AnnotationView"
        @IBOutlet weak var imageView: UIImageView!
    
        var lines :[Line] = []
        var lastPoint:CGPoint!
        let drawingLayer = CAShapeLayer()
    
        override func awakeFromNib() {
            super.awakeFromNib()
            layer.addSublayer(drawingLayer)
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
            lastPoint = touches.first?.location(in: self)
        }
    
        override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
            if let touch  = touches.first
            {
                let newPoint = touch.location(in:self)
                lines.append(Line(start: lastPoint, end: newPoint))
                lastPoint = newPoint
                updateDrawingOverlay()
            }
        }
    
        func updateDrawingOverlay() {
            let path = CGMutablePath()
    
            for line in lines {
                path.move(to: line.startPoint)
                path.addLine(to: line.endPoint)
            }
    
            drawingLayer.frame = imageView.frame
            drawingLayer.path = path
            drawingLayer.lineWidth = 5
            drawingLayer.strokeColor = UIColor.black.cgColor
    
            setNeedsDisplay()
        }
    }
    

    这应该可以解决问题,让我知道它是怎么回事。

    【讨论】:

    • 感谢您的快速回复,但它没有绘制任何有/没有图像的东西......
    • @neena 请尝试复制粘贴新版本,我将init(frame:) 替换为awakeFromNib(),以确保在添加叠加层之前加载您的图像视图。让我知道是否有效。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-30
    • 1970-01-01
    • 2016-05-26
    • 1970-01-01
    相关资源
    最近更新 更多