iphone - 无法通过平滑的徒手绘图来包含撤消/重做

标签 iphone drawrect quartz-core

很多天以来一直在与问题作斗争。希望我能在这里得到答案。我用过this链接以平滑我的手绘图。在这段代码中,我能够设置线宽和颜色,但是当我尝试使用 this 在其中包含撤消/重做功能时,我发现它非常困难。链接在撤消重做方面工作正常,但徒手绘制并不流畅。

经过一些研究和编码,我知道这是绘图的阻碍,我认为这阻止了撤消/重做。

在第一个链接中有一个文件“CachedLIView.h/m”,当我使用它并尝试在其中包含撤消/重做时,我发现在以下方法中:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event // (2)
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path addLineToPoint:p];

    [self drawBitmap]; // (3)
    [self setNeedsDisplay];

    [path removeAllPoints]; //(4)
}

此方法正在调用drawBitMap:方法,该方法实际上在每次用户抬起手指并同时从“路径”中删除点时生成临时图像。

- (void)drawBitmap // (3)
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0);
    [[UIColor blackColor] setStroke];
    if (!incrementalImage) // first draw; paint background white by ...
    {
        UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object
        [[UIColor greenColor] setFill];
        [rectpath fill]; // filling it with white
    }
    [incrementalImage drawAtPoint:CGPointZero];
    //[path stroke];
    for (UIBezierPath *_path in pathArray)
        [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

我将每个路径保存在数组中,以便我可以撤消/重做。 (从第二个链接中获取这个想法)。

下面是我修改后包含撤消/重做的该文件的完整代码:

    #import "CachedLIView.h"

@implementation CachedLIView
{
    UIBezierPath *path;
    UIImage *incrementalImage; // (1)
}

- (id)initWithFrame:(CGRect)frame // (1)
{
    if (self = [super initWithFrame:frame])
    {
        [self setMultipleTouchEnabled:NO]; // (2)
        //        [self setBackgroundColor:[UIColor whiteColor]];
//                path = [[UIBezierPath alloc] init];
//                [path setLineWidth:3];

        pathArray=[[NSMutableArray alloc]init];
        bufferArray=[[NSMutableArray alloc]init];
        [self drawBitmap];
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    NSLog(@"in drawrect pathArray[count]: %d", pathArray.count);

    [incrementalImage drawInRect:rect]; // (3)

    //[[UIColor blackColor] setStroke];
    //[path stroke];
    for (UIBezierPath *_path in pathArray)
        [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    path = [[UIBezierPath alloc] init];
    path.lineWidth = 3;

    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path moveToPoint:p];

    [pathArray addObject:path];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path addLineToPoint:p];


    [self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event // (2)
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path addLineToPoint:p];

    [self drawBitmap]; // (3)
    [self setNeedsDisplay];

    [path removeAllPoints]; //(4)
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesEnded:touches withEvent:event];
}

- (void)drawBitmap // (3)
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0);
    [[UIColor blackColor] setStroke];
    if (!incrementalImage) // first draw; paint background white by ...
    {
        UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object
        [[UIColor greenColor] setFill];
        [rectpath fill]; // filling it with white
    }
    [incrementalImage drawAtPoint:CGPointZero];
    //[path stroke];
    for (UIBezierPath *_path in pathArray)
        [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

#pragma mark - undo/redo
-(void)undoButtonClicked
{
    if([pathArray count]>0){
        UIBezierPath *_path=[pathArray lastObject];
        [bufferArray addObject:_path];
        [pathArray removeLastObject];

        [self drawBitmap];
        [self setNeedsDisplay];
    }
}

-(void)redoButtonClicked
{
    if([bufferArray count]>0){
        UIBezierPath *_path=[bufferArray lastObject];
        [pathArray addObject:_path];
        [bufferArray removeLastObject];

        [self drawBitmap];
        [self setNeedsDisplay];
    }
}
@end

.h 文件是:

#import <UIKit/UIKit.h>

@interface CachedLIView : UIView
{
    NSMutableArray *pathArray;
    NSMutableArray *bufferArray;
    UIBezierPath *myPath;

}
-(void)undoButtonClicked;
-(void)redoButtonClicked;
@end

请帮助我。我做错了什么。 pathArray 计数工作正常。但无法在屏幕上显示撤消/重做效果。

最佳答案

嘿,我无法获得您的完整代码,但我可以建议您我们如何实现这样的事情,

对于徒手图像绘制中的重做和撤消,您可以在触摸开始或触摸结束时捕获图像渲染,并管理该堆栈渲染。然后根据您的要求(重做/撤消)使用缓存中的渲染。所以步骤就像,

1) 当您触摸板时捕获渲染并保存。并在缓存中管理该序列。

  • 因此,每次触摸开始时,您都必须捕获图像并按顺序保存。

2)当您按下撤消键时,获取最后的渲染并将其替换为您的板。

3) 对于重做,您可以检查是否有比当前替换的渲染更高的渲染可用。意味着您可以通过最后更新的渲染来启用和禁用该按钮。

4)完成保存图像后不要忘记清空缓存,这样您就可以管理下一次绘图的堆栈。

<小时/>
  • 如果您不明白这个想法,请告诉我。

关于iphone - 无法通过平滑的徒手绘图来包含撤消/重做,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13744160/

相关文章:

iphone - Phonegap 在启动画面后显示白屏 - IOS

iphone - 获得苹果批准后我们可以拒绝应用程序吗?

ios - iOS 中的描边蒙版 CALayer

ios - 如何将 UIView 的显示复制到另一个窗口中?

ios - 我可以在 drawRect 方法之外绘制圆形、矩形、直线等形状吗

ios - 基于iOS定位的图层蒙版

iphone - 将 NSArray 写回 plist

html - iOS 8 html输入文件控件选择 "Take Photo"选项时黑屏

uiscrollview - drawRect 使 UIScrollView 中的滚动速度变慢

iphone - UIBezierPath 路径太多 = 太慢?