Chr*_*bin 2 core-graphics ios swift
我正在尝试在Swift 2中创建绘图应用程序,并且在尝试实现“撤消”按钮时碰到了墙。我对此很陌生(实际上是非常新的),并且尽了最大的努力弄清楚了,但是我发现的所有其他示例都使用不同的版本或语言,或者根本不适用。也许是由于我缺乏知识阻碍了我在这里的进步。
我已经尝试过使用“ undoManager”,但是我不知道如何使用它。我尝试阅读可用的在线指南,但仍然一无所知!
这是我的按钮:
@IBAction func undoDrawing(sender: AnyObject) {
}
Run Code Online (Sandbox Code Playgroud)
我已经建立了touchesBegan:
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?){
isSwiping = false
if let touch = touches.first{
lastPoint = touch.locationInView(imageView)
}
}
Run Code Online (Sandbox Code Playgroud)
touchesMoved:
override func touchesMoved(touches: Set<UITouch>,
withEvent event: UIEvent?){
isSwiping = true;
if let touch = touches.first{
let currentPoint = touch.locationInView(imageView)
UIGraphicsBeginImageContext(self.imageView.frame.size)
self.imageView.image?.drawInRect(CGRectMake(0, 0, self.imageView.frame.size.width, self.imageView.frame.size.height))
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y)
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y)
CGContextSetLineCap(UIGraphicsGetCurrentContext(),CGLineCap.Round)
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), myCGFloat)
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), self.selectedColor.CGColor)
CGContextStrokePath(UIGraphicsGetCurrentContext())
self.imageView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
lastPoint = currentPoint
}
}
Run Code Online (Sandbox Code Playgroud)
和touchesEnded:
override func touchesEnded(touches: Set<UITouch>,
withEvent event: UIEvent?){
if(!isSwiping) {
UIGraphicsBeginImageContext(self.imageView.frame.size)
self.imageView.image?.drawInRect(CGRectMake(0, 0, self.imageView.frame.size.width, self.imageView.frame.size.height))
CGContextSetLineCap(UIGraphicsGetCurrentContext(), CGLineCap.Round)
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), myCGFloat)
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), self.selectedColor.CGColor)
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y)
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y)
CGContextStrokePath(UIGraphicsGetCurrentContext())
self.imageView.image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
}
}
Run Code Online (Sandbox Code Playgroud)
因此,我所需要的只是一种方法,可以逆转这些“接触”所采取的动作。有任何想法吗?
我可以想到两种解决方法,简单限制方法和硬性概括方法。
最简单的方法(仅允许撤消单个更改)是在内存中维护映像的第二个副本。用伪代码,
// Update contents of backupImage, draw new line on currentImage
drawNewLine {
backupImage = currentImage
drawLineOnCurrentImage()
}
// Revert currentImage to most-recent backupImage
undo {
currentImage = backupImage
}
Run Code Online (Sandbox Code Playgroud)
这类似于原始MacPaint使用的方案(请参阅“问题3:如何撤消?”)。
此方法不允许重做,也不需要(或不允许使用)NSUndoManager。
对于更通用的解决方案,您需要弄清楚如何将每个绘图事件表示为可逆函数。
原始示例应用
想象一下,绘图应用程序支持的唯一操作是缩放。从而,
scale(image, 2.0) // push 2.0 onto stack - current size = 2.0x
scale(image, 3.0) // push 3.0 onto stack - current size = 6.0x
Run Code Online (Sandbox Code Playgroud)
返回的图像是大小的六倍。您可以使用一堆浮点数来表示此操作,例如scaleHistory = [2.0, 3.0]。
然后,您的撤消功能将是
undo(image) {
scale(image, 1 / scaleHistory.lastObject())
scaleHistory.removeLastObject()
}
Run Code Online (Sandbox Code Playgroud)
从上方继续执行,
undo(image) // Pop 3.0 from the stack. Scale by 1 / 3.0, new size = 2.0x
undo(image) // Pop 2.0 from the stack. Scale by 1 / 2.0, new size = 1.0x
Run Code Online (Sandbox Code Playgroud)
现在scaleHistory是空的,您应该禁用该undo按钮!
这是期望的范式NSUndoManager; 请参阅本文,其中介绍了撤消堆栈的用法。
如何在您的应用程序中完成这项工作
我看到的一种实现此范例的方法是,用数据结构中记录绘图动作的意图直接替换图像上的绘图。因此,您将有一个CGPoint成对的向量,代表用户添加的行。用伪代码,
lines = []
addLine(start, finish) {
lines.addObject((start, finish))
draw()
}
draw() {
canvas = nil
foreach (lines as line) {
canvas.paintToScreen(line) // this function invokes CGContextMoveToPoint, CGContextAddLineToPoint, etc.
}
}
undo() {
lines.removeLastObject()
draw()
}
canUndo() {
return lines.count > 0
}
Run Code Online (Sandbox Code Playgroud)
至关重要的是,您必须canvas在每次调用时重设您的位置,draw()以确保输入的每一行都lines被精确渲染一次。
当然,这并不是缩放应用程序的精确模拟,因为undo()它不只是应用最后一个操作的逆函数。相反,我们重置屏幕上的图像- 等同于撤消所有操作 -然后有选择地重新执行我们要保留在draw()功能中的图像。
| 归档时间: |
|
| 查看次数: |
1741 次 |
| 最近记录: |