UIBezierPath 撤销绘制重绘 UIImageView 的图像 [英] UIBezierPath undo drawing redraw UIImageView's image

查看:132
本文介绍了UIBezierPath 撤销绘制重绘 UIImageView 的图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to redraw my UIImageView's image by redrawing all UIBezierPaths and associated UIColors in an NSMutableArray I have created, minus the last path when I tap an undo UIButton.

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

However, the UIImageView's image doesn't redraw and remove the last path in this case, until the NSMutableArray's count is less than 2, in which it sets the UIImageView's image to nil (this is working correctly)

如果您提供任何帮助,我将不胜感激.注意:我不包括我的 touchesMoved 方法,因为我只想暂时撤消点".

I'd appreciate any help offered. Note: I'm not including my touchesMoved method because I just want to get undoing 'dots' to work for now.

**

**

- (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.因此,您目前所做的就是在旧线条上重新绘制线条.

You don't clear self.drawingImageView.image before you start doing your redraw of the remaining paths. So, all you're currently doing is redrawing the lines over the old lines.

你应该做的是:

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

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

then, at the end, get the new image from the context (image = UIGraphicsGetImageFromCurrentImageContext()) and save it in 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;

这篇关于UIBezierPath 撤销绘制重绘 UIImageView 的图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆