gpt4 book ai didi

iOS 创建 CAShapeLayer 蒙版的反面

转载 作者:可可西里 更新时间:2023-11-01 04:41:58 25 4
gpt4 key购买 nike

所以我是一名 iOS 开发新手,正在开发一个 iOS 绘图应用程序,该应用程序使用 x/y 坐标和时间戳来回放用户草图。为了绘制简单的笔事件,我有一个 UIView 作为绘图 View ,我使用 CAShapeLayers 绘制到 View ,如下所示:

if (index == 0){
CGPathMoveToPoint(path, NULL, point.x, point.y);
} else {
CGPathAddLineToPoint(path, NULL, point.x, point.y);
}

……

CAShapeLayer *permLayer = [CAShapeLayer layer];
[permLayer setFrame:CGRectMake(0, 0, 1024, 640)];
[permLayer setFillColor:[[UIColor clearColor] CGColor]];
[permLayer setStrokeColor:currentColor.CGColor];
[permLayer setLineWidth:[event[@"strokeWeight"] floatValue]];
[permLayer setLineJoin:kCALineJoinRound];
[permLayer setLineCap:kCALineCapRound];

……

[[self layer] addSublayer:permLayer];

……

一切都很好,看起来很好:

enter image description here

现在我想要做的是有一个看起来像这样的删除事件:

enter image description here

我尝试使用另一个 CAShapeLayer 作为掩码并将删除事件的 CGPath 绘制到该掩码来完成此操作。然而,我最终得到的是:

enter image description here

......这与我想要的完全相反。我想我需要以某种方式获取由删除事件的 CGPath 创建的 CAShapeLayer 的逆掩码?如果没有大量我不熟悉的数学知识,我不确定解决这个问题的正确方法是什么。

另一个需要注意的是,此动画与 CADisplayLink 相关联,因此这些绘图动画会经常刷新,性能很重要。我之前尝试过绘制到 UIImages 而不是 CAShapeLayers 并使用 kCGBlendModeClear 来实现删除效果,但性能受到了极大的影响。感谢您提供任何建议或见解!

最佳答案

I guess I need to somehow get the inverse mask of the CAShapeLayer created by the CGPath of the erase event?

您要求的“反向掩码”不是 CAShapeLayer 可以描述的东西(至少没有直接的解决方案)。如果您想继续使用 CAShapeLayer,请添加带有图像背景色的“删除路径”。

但是,如果我正确理解您的实现,我会看到另一个问题:您为用户的每个笔划添加一个子层。如果用户用很多笔画绘制复杂的图片,您最终会得到一个巨大的图层堆栈,这肯定会在某些时候导致性能问题。

我会建议切换到另一种方法并绘制到图像缓冲区。听起来您尝试过但由于性能原因而放弃了该方法 - 但如果正确完成,性能会非常好。

创建你自己的位图上下文

_context = CGBitmapContextCreate(...);

并在您的 touchesBegan/Moved 方法中像这样绘制到该上下文:

if(isEraseEvent)
CGContextSetBlendMode(_context, kCGBlendModeClear);
else
CGContextSetBlendMode(_context, kCGBlendModeNormal);

// Configure your current stroke: lineWidth, color etc.
CGContextSetLineWidth(_context, _currentStroke.lineWidth);

// Added stroke from point p to point q
CGContextMoveToPoint(_context, p.x, p.y);
CGContextAddLineToPoint(_context, q.x, q.y);
CGContextStrokePath(_context);

在每个这样的事件之后,显示上下文。您可以将整个上下文渲染到 UIImage 并显示 UIImage,但性能可能会受到影响。相反,让渲染由带有委托(delegate)的 CALayer 完成。让委托(delegate)实现方法

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
CGImageRef tempImage = CGBitmapContextCreateImage(_context);
CGContextDrawImage(ctx, self.bounds, tempImage);
CGImageRelease(tempImage);
}

不要忘记告诉图层它的内容在您绘制到上下文时发生了变化。调用 setNeedsDisplay 会重新显示完整的层,这在大多数情况下超出了您的需要。改为做这样的事情:

CGRect r = CGRectMake(MIN(p.x, q.x),
MIN(p.y, q.y),
ABS(p.x-q.x),
ABS(p.y-q.y));

CGFloat inset = ...;
[_theLayer setNeedsDisplayInRect:CGRectInset(r, inset, inset)];

确保您仅重新渲染内容实际更改的图像部分。 inset 应该是一些(负)插入,以考虑您的笔划宽度。

请注意,我在上面写的所有内容(上下文创建除外)都会为每个 touchesMoved 事件调用一次,即笔划在用户输入时渲染和显示(或者,在你的情况下,绘图过程被重播)并且你永远不需要渲染或显示更多。

关于iOS 创建 CAShapeLayer 蒙版的反面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18498525/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com