【问题标题】:UIBezierPath undo drawing redraw UIImageView's imageUIBezierPath 撤消绘制重绘 UIImageView 的图像
【发布时间】:2014-03-02 05:52:20
【问题描述】:

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

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

如果能提供任何帮助,我将不胜感激。注意:我没有包括我的 touchesMoved 方法,因为我现在只想让撤消“点”工作。

**

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

**

- (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];
}

【问题讨论】:

    标签: ios objective-c uiimageview nsmutablearray uibezierpath


    【解决方案1】:

    在开始重绘剩余路径之前,您没有清除 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;
    

    【讨论】:

    • 感谢您的更新。我会在一分钟内试试这个。快速提问,在我的 touchesMoved 方法中,如果我不使用异步调度,您将无法实时看到您绘制的路径。当然有更好的方法。
    • 通常我不会在触摸时不断地渲染成图像。我会将当前路径渲染到图像前面的图层中,然后在触摸会话完成后将路径渲染到图像中。
    • 具体来说, CGContextDrawLayerAtPoint ?我需要为此打开一个新问题吗
    • 可能。 CGContextDrawLayerAtPoint 会将图层渲染到上下文中(如图像上下文)。
    • 这比我目前糟糕的实现效率高得多?
    猜你喜欢
    • 1970-01-01
    • 2015-12-09
    • 2018-10-21
    • 1970-01-01
    • 2016-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多