gpt4 book ai didi

ios - 如何忽略多点触控序列中的某些 UITouch 点

转载 作者:可可西里 更新时间:2023-11-01 05:29:35 24 4
gpt4 key购买 nike

我正在为 ipad 开发一个绘图应用程序,我提供全屏绘图。所以就像我们现在一样,用户可能会用手腕支撑或将手放在屏幕上进行书写。所以我的目标是让用户在手腕/手部支撑下自由书写。

但应用程序应该只检测手指画画,或者忽略/拒绝手腕和手部触摸并删除它们

我开始研究它,我创建了一个启用了多点触控的示例项目。

下面是我的代码

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

mouseSwiped = NO;

for (UITouch *touch in touches)
{
NSString *key = [NSString stringWithFormat:@"%d", (int) touch];
lastPoint = [touch locationInView:self.view];

[touchPaths setObject:[NSValue valueWithCGPoint:lastPoint] forKey:key];
}

}


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
mouseSwiped = YES;
CGPoint lastPoint3;

for (UITouch *touch in touches)
{
NSString *key = [NSString stringWithFormat:@"%d", (int) touch];

lastPoint = [[touchPaths objectForKey:key] CGPointValue];


currentPoint1 = [touch locationInView:self.view];

NSLog(@"Y:%f",currentPoint1.y);


UIGraphicsBeginImageContext(self.view.frame.size);
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush );
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1.0);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(),kCGBlendModeNormal);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint1.x, currentPoint1.y);

CGContextStrokePath(UIGraphicsGetCurrentContext());
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self.tempDrawImage setAlpha:opacity];
UIGraphicsEndImageContext();

[touchPaths setObject:[NSValue valueWithCGPoint:currentPoint1] forKey:key];
}
}

所以这适用于任意数量的触摸,但我不明白如何在绘图时拒绝那些手掌/手触摸,只绘制用户用他的手指/手写笔绘制的内容。

目前如果我画画,我得到这个东西,下面是图像

这里是我用手撑画的,你可以在“你好”下面看到他们画了一些奇怪的画。我怎么能拒绝那些触摸并删除它们只画你好

谢谢

兰 git

最佳答案

一种解决方案是将最上面的点击存储在 touchesBegan 中,并且只绘制这个。

正如您所指出的,您不应该保留 UITouch 实例,因此我建议改用弱引用。

这只会绘制一个触摸。如果你想绘制多个手指的触摸,你需要另一种过滤掉手的方法(例如,许多绘图应用程序有用户设置来告诉应用程序手的姿势,但这当然更复杂)。

这里有一个关于如何做到这一点的想法:

#import <QuartzCore/QuartzCore.h>

@interface TViewController () {
// We store a weak reference to the current touch that is tracked
// for drawing.
__weak UITouch* drawingTouch;
// This is the previous point we drawed to, or the first point the user tapped.
CGPoint touchStartPoint;
}
@end
@interface _TDrawView : UIView {
@public
CGLayerRef persistentLayer, tempLayer;
}
-(void)commitDrawing;
-(void)discardDrawing;
@end

@implementation TViewController

- (void) loadView
{
self.view = [[_TDrawView alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.view.opaque = YES;
self.view.multipleTouchEnabled = YES;
self.view.backgroundColor = [UIColor whiteColor];
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
// Start with what we currently have
UITouch* topmostTouch = self->drawingTouch;
// Find the top-most touch
for (UITouch *touch in touches) {
CGPoint lastPoint = [touch locationInView:self.view];
if(!topmostTouch || [topmostTouch locationInView:self.view].y > lastPoint.y) {
topmostTouch = touch;
touchStartPoint = lastPoint;
}
}
// A new finger became the drawing finger, discard any previous
// strokes since last touchesEnded
if(self->drawingTouch != nil && self->drawingTouch != topmostTouch) {
[(_TDrawView*)self.view discardDrawing];
}
self->drawingTouch = topmostTouch;
}

- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// Always commit the current stroke to the persistent layer if the user
// releases a finger. This could need some tweaking for optimal user experience.
self->drawingTouch = nil;
[(_TDrawView*)self.view commitDrawing];
[self.view setNeedsDisplay];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
const CGFloat red=0, green=0, blue=0, brush=1;
for (UITouch *touch in touches) {
// Find the touch that we track for drawing
if(touch == self->drawingTouch) {
CGPoint currentPoint = [touch locationInView:self.view];

// Draw stroke first in temporary layer
CGContextRef ctx = CGLayerGetContext(((_TDrawView*)self.view)->tempLayer);
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineWidth(ctx, brush );
CGContextSetRGBStrokeColor(ctx, red, green, blue, 1.0);
CGContextSetBlendMode(ctx,kCGBlendModeNormal);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, touchStartPoint.x, touchStartPoint.y);
CGContextAddLineToPoint(ctx, currentPoint.x, currentPoint.y);
CGContextStrokePath(ctx);
// Update the points so that the next line segment is drawn from where
// we left off
touchStartPoint = currentPoint;
// repaint the layer
[self.view setNeedsDisplay];
}
}
}

@end

@implementation _TDrawView

- (void) finalize {
if(persistentLayer) CGLayerRelease(persistentLayer);
if(tempLayer) CGLayerRelease(tempLayer);
}

- (void) drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
if(!persistentLayer) persistentLayer = CGLayerCreateWithContext(ctx, self.bounds.size, nil);
if(!tempLayer) tempLayer = CGLayerCreateWithContext(ctx, self.bounds.size, nil);

// Draw the persistant drawing
CGContextDrawLayerAtPoint(ctx, CGPointMake(0, 0), persistentLayer);
// Overlay with the temporary drawing
CGContextDrawLayerAtPoint(ctx, CGPointMake(0, 0), tempLayer);
}

- (void)commitDrawing {
// Persist the temporary drawing
CGContextRef ctx = CGLayerGetContext(persistentLayer);
CGContextDrawLayerAtPoint(ctx, CGPointMake(0, 0), tempLayer);
[self discardDrawing];
}
- (void)discardDrawing {
// Clears the temporary layer
CGContextRef ctx = CGLayerGetContext(tempLayer);
CGContextClearRect(ctx, self.bounds);
CGContextFlush(ctx);
}
@end

编辑:我添加了这样的逻辑,即如果检测到新触摸,如果当前正在绘制任何具有更高 y 值的笔画,它将被删除,正如我们在评论中所讨论的那样。

覆盖是通过绘制两个 CGLayer 完成的。此代码可以针对性能进行大量优化,应将其更多地视为示例,而不是生产就绪代码。

关于ios - 如何忽略多点触控序列中的某些 UITouch 点,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20853765/

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