【发布时间】:2017-02-08 23:53:24
【问题描述】:
我想在UIImageView, 上绘制一个“消失的笔触”,它会在触摸事件之后并在固定的时间延迟后自擦除。这是我的 ViewController 中的内容。
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
CGPoint lp = lastPoint;
UIColor *color = [UIColor blackColor];
[self drawLine:5 from:lastPoint to:currentPoint color:color blend:kCGBlendModeNormal];
double delayInSeconds = 1.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self drawLine:brush from:lp to:currentPoint color:[UIColor clearColor] blend:kCGBlendModeClear];
});
lastPoint = currentPoint;
}
- (void)drawLine:(CGFloat)width from:(CGPoint)from to:(CGPoint)to color:(UIColor*)color blend:(CGBlendMode)mode {
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextMoveToPoint(context, from.x, from.y);
CGContextAddLineToPoint(context, to.x, to.y);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, width);
CGContextSetStrokeColorWithColor(context, [color CGColor]);
CGContextSetBlendMode(context, mode);
CGContextStrokePath(context);
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self.tempDrawImage setAlpha:1];
UIGraphicsEndImageContext();
}
绘制阶段运行良好,但随后的擦除阶段存在一些问题。
- 当“填充”线被正确清除时,路径周围的细笔划仍然存在。
- “擦除阶段”是不稳定的,远没有绘制阶段那么平滑。我最好的猜测是,这是由于
UIGraphicsBeginImageContext在dispatch_after中运行的成本。
有没有更好的方法来绘制一条自擦除线?
奖励:我真正想要的是“缩小并消失”的路径。换句话说,在延迟之后,而不是仅仅清除描边路径,我想让它从 5pt 缩小到 0pt,同时淡出不透明度。
【问题讨论】:
-
创建一个图形上下文,在其中绘制并捕获图像是一种非常昂贵的方法。我建议改为使用 UIView 的自定义子类并覆盖
drawRect。然后,您可以直接在当前图形上下文中执行绘图命令。您可以在视图上发出 setNeedsDisplay 以触发要更新的视图。您可能希望在擦除阶段比绘制阶段稍微增加笔画宽度(尝试大 1/2 点)。 -
@DuncanC 谢谢。是的,我刚刚意识到增加笔画宽度可以解决鬼轮廓问题。我会试试你的 drawInRect 建议。干杯!
-
擦除策略不是一个好主意......如果你画一个循环排序的东西,新线穿过旧线,旧线被擦除,新线将被擦除为好在路口。
-
不是 drawInRect,
drawRect()。当需要更新其内容时,这是在自定义视图上调用的方法。实际上,您最好在每次更新时以新状态绘制整个视图,而不是尝试擦除旧的路径段。 (@spinalwrap 关于自交叉路径的观点是您在使用擦除方法时将面临的问题之一。) -
如果我这样做,我想我会使用 CAShapeLayer 并对其进行动画更改。
标签: ios objective-c uiimageview cgcontext