Swift - 使用CGContext用手指画图

Swift - Using CGContext to draw with finger

我正在尝试制作一个绘图应用程序。我有一个自定义 UIView:

class DrawView: UIView {

var touch : UITouch!
var lastPoint : CGPoint!
var currentPoint : CGPoint!

override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
    touch = touches.first as! UITouch
    lastPoint = touch.locationInView(self)
    println(lastPoint)
}

override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
    touch = touches.first as! UITouch
    currentPoint = touch.locationInView(self)

    self.setNeedsDisplay()

    lastPoint = currentPoint
}

override func drawRect(rect: CGRect) {
    var context = UIGraphicsGetCurrentContext()
    CGContextSetLineWidth(context, 5)
    CGContextSetStrokeColorWithColor(context, UIColor.blueColor().CGColor)
    CGContextSetLineCap(context, kCGLineCapRound)

    CGContextBeginPath(context)

    if lastPoint != nil {
        CGContextMoveToPoint(context, lastPoint.x, lastPoint.y)
        CGContextAddLineToPoint(context, currentPoint.x, currentPoint.y)
    }

    CGContextStrokePath(context)
}

}

然而,当我 运行 它时,我得到的只是一个蓝点跟随我的手指,但没有线条?

我做错了什么?

两件事:

  1. 调用 self.setNeedsDisplay 不会立即调用 drawRect。它只是设置一个标志,以便 drawRect 在不久的将来被调用。由于您在那之后立即将 lastPoint 设置为 currentPoint,因此当调用 drawRect 时,lastPoint 始终等于 currentPoint.

  2. drawRect 每次调用时都会重新绘制整个视图,因此您最多只能看到最近的一行。如果你解决了问题 1,你的手指后面会有一条短线而不是一个点。如果你想看到整个轨迹,你需要将点存储在一个数组中,该数组是你视图的 属性,然后画线连接 drawRect 中的所有点。

您好,我做了一些简单的更改并修复了您的代码,希望它对以后的人有所帮助(代码已更新为 Swift 3):

class DrawView: UIView {

    var touch : UITouch!
    var lineArray : [[CGPoint]] = [[CGPoint]()]
    var index = -1

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

        index += 1
        lineArray.append([CGPoint]())
        lineArray[index].append(lastPoint)
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        touch = touches.first! as UITouch
        let currentPoint = touch.location(in: self)

        self.setNeedsDisplay()

        lineArray[index].append(currentPoint)
    }

    override func draw(_ rect: CGRect) {

        if(index >= 0){
            let context = UIGraphicsGetCurrentContext()
            context!.setLineWidth(5)
            context!.setStrokeColor((UIColor(red:0.00, green:0.38, blue:0.83, alpha:1.0)).cgColor)
            context!.setLineCap(.round)

            var j = 0
            while( j <= index ){
                context!.beginPath()
                var i = 0
                context?.move(to: lineArray[j][0])
                while(i < lineArray[j].count){
                    context?.addLine(to: lineArray[j][i])
                    i += 1
                }
                context!.strokePath()
                j += 1
            }
        }
    }
}

marcomoreira92 和 Keuha 的版本对我有用,但我不太喜欢使用索引。因此这是一个替代版本,在 Swift 4.2:

中测试过
class DrawView: UIView {

    var lineArray: [[CGPoint]] = [[CGPoint]]()

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        let firstPoint = touch.location(in: self)
        lineArray.append([CGPoint]())
        lineArray[lineArray.count - 1].append(firstPoint)
    }

    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
        guard let touch = touches.first else { return }
        let currentPoint = touch.location(in: self)
        lineArray[lineArray.count - 1].append(currentPoint)
        setNeedsDisplay()
    }

    override func draw(_ rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()
        context?.setLineWidth(5)
        context?.setStrokeColor(UIColor.black.cgColor)
        context?.setLineCap(.round)

        for line in lineArray {
            guard let firstPoint = line.first else { continue }
            context?.beginPath()
            context?.move(to: firstPoint)
            for point in line.dropFirst() {
                context?.addLine(to: point)
            }
            context?.strokePath()
        }
    }
}