gpt4 book ai didi

ios - 使用 CGContextRef 绘制自删除路径

转载 作者:行者123 更新时间:2023-11-29 00:30:04 25 4
gpt4 key购买 nike

我想在 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();
}

绘制阶段运行良好,但后续删除阶段存在一些问题。

  1. 虽然“填充”线被正确清除,但路径周围仍然有细笔画。
  2. “删除阶段”起伏不定,远不及绘图阶段那么流畅。我最好的猜测是,这是由于 UIGraphicsBeginImageContextdispatch_after 中运行的成本所致。

有没有更好的方法来绘制自擦线?

奖励:我真正喜欢的是“缩小和消失”的路径。换句话说,在延迟之后,我不想只是清除描边路径,而是让它从 5pt 缩小到 0pt,同时淡出不透明度。

最佳答案

我会让 View 以 60 Hz 的频率连续绘制,并且每次使用存储在数组中的点绘制整条线。这样,如果您从数组中删除最旧的点,它们将不再被绘制。

要连接 View 以显示刷新率(60 Hz),请尝试以下操作:

displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(update)];
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];

将年龄属性与每个点一起存储,然后循环遍历数组并删除早于阈值的点。

例如

@interface AgingPoint <NSObject>
@property CGPoint point;
@property NSTimeInterval birthdate;
@end

// ..... later, in the draw call

NSTimeInterval now = CACurrentMediaTime();

AgingPoint *p = [AgingPoint new];
p.point = touchlocation; // get yr touch
p.birthdate = now;

// remove old points
while(myPoints.count && now - [myPoints[0] birthdate] > 1)
{
[myPoints removeObjectAtIndex: 0];
}
myPoints.add(p);

if(myPoints.count < 2)
return;

UIBezierPath *path = [UIBezierPath path];
[path moveToPoint: [myPoints[0] point]];
for (int i = 1; i < myPoints.count; i++)
{
[path lineToPoint: [myPoints[i] point];
}

[path stroke];

因此,在每次绘制调用时,创建一个新的贝塞尔路径,移动到第一个点,然后向所有其他点添加线条。最后,划线。

要实现“收缩”线,您可以在数组中的连续点对之间绘制短线,并使用age属性来计算笔画宽度。这并不完美,因为各个线段在起点和终点处具有相同的宽度,但它是一个起点。

重要提示:如果您要获得很多积分,性能将成为一个问题。这种使用 Quartz 的路径渲染并没有完全调整为真正快速渲染。事实上,它非常非常慢。

Cocoa 数组和对象也不是很快。

如果您遇到性能问题并且想要继续此项目,请研究 OpenGL 渲染。通过将纯 C 结构插入 GPU,您将能够更快地运行该程序。

关于ios - 使用 CGContextRef 绘制自删除路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42125817/

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