ios - UIBezierPath 撤消绘图重绘 UIImageView 的图像

标签 ios objective-c uiimageview nsmutablearray uibezierpath

我正在尝试通过重绘我创建的 NSMutableArray 中的所有 UIBezierPath 和关联的 UIColor 来重绘 UIImageView 的图像,减去点击撤消 UIButton 时的最后一个路径。

但是,在这种情况下,UIImageView 的图像不会重绘并删除最后一条路径,直到 NSMutableArray 的计数小于 2,此时它将 UIImageView 的图像设置为 nil(这是正常工作的)

如果您提供任何帮助,我将不胜感激。注意:我不包括 TouchMoved 方法,因为我现在只想撤消“点”。

**

更新:这是我最终使用的代码,在下面接受的答案的帮助下:

**

- (void)undoLast
{
    if (self.drawingPathArray.count < 2)
    {
        self.drawingPathArray = nil;
        self.undoButton.hidden = YES;
        self.drawingImageView.image = nil;
    }
    else
    {
        [self.drawingPathArray removeLastObject];

        self.undoButton.tintColor = [[self.drawingPathArray lastObject] objectAtIndex:0];

        UIGraphicsBeginImageContextWithOptions(self.drawingImageView.bounds.size, NO, 0.0);

        for (NSArray *subArray in self.drawingPathArray)
        {
            CGContextRef context = UIGraphicsGetCurrentContext();
            CGContextSetLineWidth(context, 3.0);
            CGContextSetLineCap(context, kCGLineCapRound);
            CGContextSetStrokeColorWithColor(context, [[subArray objectAtIndex:0] CGColor]);
            CGContextAddPath(context, [[subArray objectAtIndex:1] CGPath]);
            CGContextStrokePath(context);
        }

        self.drawingImageView.image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }
}

原始问题的代码:

@property (nonatomic, strong) NSMutableArray *drawingPathArray;
@property (nonatomic, assign) NSInteger ctr;
@property (nonatomic, assign) CGPoint lastPoint;
CGPoint pts[4];

- (void)undoLast
{
    if (self.drawingPathArray.count < 2)
    {
        self.drawingPathArray = nil;
        self.undoButton.hidden = YES;
        self.drawingImageView.image = nil;
    }
    else
    {
        [self.drawingPathArray removeLastObject];

        NSArray *lastArray = [self.drawingPathArray lastObject];

        UIColor *lastColor = [lastArray objectAtIndex:0];

        self.undoButton.tintColor = lastColor;

        for (NSArray *subArray in self.drawingPathArray)
        {
            // These colors and paths are getting set correctly, verified by using NSLog
            UIColor *color = [subArray objectAtIndex:0];
            UIBezierPath *path = [subArray objectAtIndex:1];

            [self drawWithPath:path andColor:color];
        }
    }
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{           
    self.ctr = 0;
    UITouch *touch = [touches anyObject];
    pts[0] = [touch locationInView:self.drawingImageView];
}

- (void)drawWithPath:(UIBezierPath *)path andColor:(UIColor *)color
{
    path.lineWidth = 3.0;
    path.lineCapStyle = kCGLineJoinRound;

    dispatch_async(dispatch_get_main_queue(),
    ^{
        UIGraphicsBeginImageContextWithOptions(self.drawingImageView.bounds.size, NO, 0.0);

        [self.drawingImageView.image drawAtPoint:CGPointZero];
        [color setStroke];
        [path stroke];
        self.drawingImageView.image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    });
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UIBezierPath *path = [UIBezierPath bezierPath];

    if (self.ctr == 0)
    {
        [path moveToPoint:pts[0]];
        [path addLineToPoint:pts[0]];
    }

    self.undoButton.hidden = NO;
    [self.undoButton setTintColor:self.inkColor];

     if (!self.drawingPathArray)
     {
        self.drawingPathArray = [[NSMutableArray alloc]init];
     }

     [self.drawingPathArray addObject:@[self.inkColor,path]];

     [self drawWithPath:path andColor:self.inkColor];
}

最佳答案

在开始重绘剩余路径之前,您没有清除 self.drawingImageView.image。因此,您当前要做的就是在旧线上重新绘制线条。

你应该做的是:

  1. 创建一个新上下文并将所有线条绘制到其中
  2. 不要将旧图像绘制到新的上下文中
  3. 不要使用 GCD 对此上下文的更新进行排队,只需内联执行(如果需要,可以在后台执行)

然后,最后从上下文中获取新图像 (image = UIGraphicsGetImageFromCurrentImageContext()) 并将其保存在 self.drawingImageView.image = image;


伪代码:

// create a new bitmap image context
UIGraphicsBeginImageContextWithOptions(...
ctx = UIGraphicsGetCurrentContext();

for (NSArray *subArray in self.drawingPathArray) {
    // get the path and colour
    CGContextSetStrokeColor(ctx, ...
    CGContextAddPath(ctx, ... (path from bezier)
    CGContextStrokePath(ctx);
}

// create image
image = UIGraphicsGetImageFromCurrentImageContext();

self.drawingImageView.image = image;

关于ios - UIBezierPath 撤消绘图重绘 UIImageView 的图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22124385/

相关文章:

ios - GMSMarker 在 GMSPolyline 上的拐角处弹跳

objective-c - 使用 NSRunAlertPanel 时的 EXC_BAD_INSTRUCTION

objective-c - iOS 自动线程?

ios - UINavigationItem titleView动画

ios - Swift 4 - swift 中带有两个圆角的 ImageView ?

iphone - 只允许用户按 UIButton 一次

android - 如何在 Xamarin 中测试所有内容

ios - 将 Xamarin Forms 中的编辑器滚动到 View 中

objective-c - Objective C 访问 NSBundle

ios - iOS 7 UIImage中的奇怪错误(延迟后未显示或显示)