在Swift中绘制新部分时删除曲线的旧部分

时间:2015-12-12 12:50:21

标签: ios swift drawing lines

我有下面的Swift 2代码,当用户触摸并在屏幕上移动手指时绘制曲线。当用户移动他们的手指以在屏幕上给出一条连续的曲线时,添加曲线的新部分。 (上图)

但是,我希望更改下面的代码,以便在添加行的每个新部分并将其绘制到屏幕时,删除前一部分和前面的部分,以便在屏幕上看到的所有部分都是新部分,没有其他的。 (下图)

需要在下面的代码部分中修改哪些内容才能实现此目的?

enter image description here

// Swift 2 code below tested using Xcode 7.0.1.

class drawLines: UIView {

let path=UIBezierPath()

var previousPoint:CGPoint = CGPoint.zero

var strokeColor:UIColor?

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

override func drawRect(rect: CGRect) {

    strokeColor = UIColor.blackColor()
    strokeColor?.setStroke()
    path.lineWidth = 10
    path.stroke()

}

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

    let touch: AnyObject? = touches.first
    let currentPoint = touch!.locationInView(self)

    path.moveToPoint(currentPoint)
    previousPoint=currentPoint
    self.setNeedsDisplay()
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch: AnyObject? = touches.first
    let currentPoint = touch!.locationInView(self)
    let midPoint = self.midPoint(previousPoint, p1: currentPoint)

    path.addQuadCurveToPoint(midPoint,controlPoint: previousPoint)
    previousPoint=currentPoint

    self.setNeedsDisplay()

    path.moveToPoint(midPoint)
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    self.setNeedsDisplay()
}

override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
    self.touchesEnded(touches!, withEvent: event)
}

func midPoint(p0:CGPoint,p1:CGPoint)->CGPoint
{
    let x=(p0.x+p1.x)/2
    let y=(p0.y+p1.y)/2
    return CGPoint(x: x, y: y)
}

}

3 个答案:

答案 0 :(得分:3)

据我所知,没有办法从UIBezierPath删除积分。您正在寻找的解决方案是将点存储在一个数组中,您可以自由地修改它,然后从该点数组创建路径。

<强>更新

我对你发布的评论重新阅读你的帖子感到有点困惑。话虽如此,我试图让下面的例子包含你需要的所有元素 - 如果我不理解你,你可能需要重新安排它们。

此代码从触摸开始点开始不断向数组添加点,包括移动时。我在最大点数上添加了一个上限,以便在需要时删除多余的线点。当用户松开手指时,我已经明确了所有要点。

注意:我试图让代码尽可能简单,以便清楚。一旦找到符合您需求的添加/删除点的正确组合,您应该考虑优化它。特别是,这假设了一种简单的绘图方法,其中所有绘图同时发生(与增量相比),这是无效的。删除多余点的方法也可以在您理解后进行优化。

import UIKit

class ViewController: UIViewController {
    var points = [CGPoint]()

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        addTouch(touches.first)
    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        addTouch(touches.first)
    }

    override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
        points.removeAll()
    }

    override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {
        points.removeAll()
    }

    func addTouch(touch: UITouch?) {
        guard let touch = touch else { return }

        let currentPoint = touch.locationInView(self.view)
        points.append(currentPoint)

        // if you want a limit on your line length, you need these lines
        // 20 is an arbitrary number
        while (points.count > 20) {
            points.removeFirst()
        }
    }
}

剩下的就是你将它添加到当前的线条图代码中,你应该好好去。

Apple在图形性能方面做了很多关于WWDC的讨论。 This one in particular might be helpful.

答案 1 :(得分:1)

每次TwoStraws推荐时,您可以保存一系列点数并重建贝塞尔曲线路径。

另一种选择是使用CAShapeLayer绘制曲线,并更改shapeBegin属性。 (当你从shapeBegin = 1.0移动到shapeBegin = 0.0时,它会截断形状的开头。)

第三个选项是编辑删除先前点的路径。 Erica Sadun在她出色的iOS开发者的Cookbook系列中有示例代码,展示了如何解析Bezier路径中的点(如果我没记错的话,它实际上使用了Bezier路径中的底层CGPath对象。)这将比每次重建你的bezier路径,但更多的工作适合你。

答案 2 :(得分:0)

如果我理解你的问题,你会想要重置 touchesBegan()方法中的路径

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

    path.removeAllPoints()

    // ...
}