Mak*_*sim 5 drawing mask objective-c cashapelayer ios
因此,我是一名新的iOS开发人员,致力于iOS绘图应用程序,该应用程序使用x/y坐标和时间戳来回放用户草图.为了绘制简单的笔事件,我有一个UIView作为绘图视图,我使用CAShapeLayers绘制到视图,如下所示:
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];
……
Run Code Online (Sandbox Code Playgroud)
一切都很好,看起来很好:

现在我想做的是有一个看似如下的擦除事件:

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

......这与我想要的完全相反.我想我需要以某种方式获得由擦除事件的CGPath创建的CAShapeLayer的反向掩码?我不确定接近这个的正确方法是没有我不熟悉的大量数学.
另一个需要注意的是,这个动画与CADisplayLink相关联,因此这些绘制动画经常被刷新,性能很重要.我之前尝试绘制UIImages而不是CAShapeLayers并使用kCGBlendModeClear来实现擦除效果,但性能却遭受了极大的损失.感谢您的任何建议或见解!
我想我需要以某种方式获取由擦除事件的 CGPath 创建的 CAShapeLayer 的反掩码?
您要求的“逆掩码”不能用 a 来描述CAShapeLayer(至少没有直接的解决方案)。如果您想保留CAShapeLayer,请添加带有图像背景颜色的“擦除路径”。
但是,如果我正确理解您的实现,我会看到另一个问题:您为用户所做的每个笔划添加一个子层。如果用户用很多笔画绘制复杂的图片,最终会得到一大堆图层,这肯定会在某些时候导致性能问题。
我建议切换到另一种方法并绘制到图像缓冲区。听起来您尝试过,但由于性能原因而放弃了该方法 - 但如果做得正确,性能会相当不错。
创建您自己的位图上下文
_context = CGBitmapContextCreate(...);
Run Code Online (Sandbox Code Playgroud)
在你的 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);
Run Code Online (Sandbox Code Playgroud)
在每个此类事件之后,显示上下文。您可以将整个上下文渲染到 UIImage 并显示 UIImage,但性能可能会受到这种方式的影响。相反,让 CALayer 和委托来完成渲染。让委托实现该方法
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
CGImageRef tempImage = CGBitmapContextCreateImage(_context);
CGContextDrawImage(ctx, self.bounds, tempImage);
CGImageRelease(tempImage);
}
Run Code Online (Sandbox Code Playgroud)
不要忘记告诉图层,每当您绘制到上下文时,其内容就会发生变化。调用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)];
Run Code Online (Sandbox Code Playgroud)
以确保仅重新渲染图像中内容实际发生更改的部分。inset应该是一些(负)插入来考虑你的笔划宽度。
请注意,我上面写的所有内容(上下文创建除外)都会为每个touchesMoved事件调用一次,即在用户输入笔划时渲染并显示笔划(或者,如您的情况,重播绘图过程)您永远不需要渲染或显示更多内容。
| 归档时间: |
|
| 查看次数: |
2677 次 |
| 最近记录: |