【问题标题】:Multitouch tracking issue多点触控跟踪问题
【发布时间】:2014-02-28 00:50:15
【问题描述】:

我在写作时使用多点触控,所以基本上我正在做的是,我正在用手支持写作,因为通常,它是如何用户权限的,我点击了这个链接How to ignore certain UITouch Points in multitouch sequence

所以,我正在做的是,我在 touchesBegan 中跟踪一个触摸对象,并仅在 touchesMoved 中使用它。一切正常,但有时在写作时,我得到了这一行

在上图中,你可以看到我的手在屏幕上写字时突然出现的粗线

这里是代码

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSLog(@"Touches began");   

    UITouch* topmostTouch = self.trackingTouch;
    for (UITouch *touch in touches)
    {
        bufIdx = 0;
        isFirstTouchPoint = YES;
        ctr = 0;

        pts[0] = [touch locationInView:self];


        if(!topmostTouch || [topmostTouch locationInView:self].y > pts[0].y)
        {
            topmostTouch = touch;
            //touchStartPoint1 = pts[0];
        }
        else
        {
            pts[0] = pts[3];
        }
    }

   if (self.trackingTouch != nil && self.trackingTouch != topmostTouch) 
   {
     [self discardDrawing];        
   }

    self.trackingTouch = topmostTouch;
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{    
        // Find the touch that we track for drawing

            CGPoint p = [self.trackingTouch locationInView:self];
            ctr++;
            pts[ctr] = p;

            if (ctr == 4)
            {
                pts[3] = midPoint(pts[2], pts[4]);

                for ( int i = 0; i < 4; i++)
                {
                    pointsBuffer[bufIdx + i] = pts[i];
                }

                bufIdx += 4;

                dispatch_async(drawingQueue, ^{
                    //UIBezierPath *offsetPath = [UIBezierPath bezierPath]; // ................. (2)

                    self.currentPath = [[DrawingPath alloc] init];                   
                    [self.currentPath setPathColor:self.lineColor];


                    if (bufIdx == 0) return;

                    LineSegment ls[4];
                    for ( int i = 0; i < bufIdx; i += 4)
                    {
                        if (isFirstTouchPoint) // ................. (3)
                        {                           
                            ls[0] = (LineSegment){pointsBuffer[0], pointsBuffer[0]};
                            [self.currentPath.path moveToPoint:ls[0].firstPoint];                      
                            isFirstTouchPoint = NO;                   
                        }
                        else
                        {
                            ls[0] = lastSegmentOfPrev;

                        }


                        float frac1 = self.lineWidth/clamp(len_sq(pointsBuffer[i], pointsBuffer[i+1]), LOWER, UPPER); // ................. (4)
                        float frac2 = self.lineWidth/clamp(len_sq(pointsBuffer[i+1], pointsBuffer[i+2]), LOWER, UPPER);
                        float frac3 = self.lineWidth/clamp(len_sq(pointsBuffer[i+2], pointsBuffer[i+3]), LOWER, UPPER);



                        ls[1] = [self lineSegmentPerpendicularTo:(LineSegment){pointsBuffer[i], pointsBuffer[i+1]} ofRelativeLength:frac1]; // ................. (5)
                        ls[2] = [self lineSegmentPerpendicularTo:(LineSegment){pointsBuffer[i+1], pointsBuffer[i+2]} ofRelativeLength:frac2];
                        ls[3] = [self lineSegmentPerpendicularTo:(LineSegment){pointsBuffer[i+2], pointsBuffer[i+3]} ofRelativeLength:frac3];



                        [self.currentPath.path  moveToPoint:ls[0].firstPoint]; // ................. (6)
                        [self.currentPath.path  addCurveToPoint:ls[3].firstPoint controlPoint1:ls[1].firstPoint controlPoint2:ls[2].firstPoint];
                        [self.currentPath.path  addLineToPoint:ls[3].secondPoint];
                        [self.currentPath.path  addCurveToPoint:ls[0].secondPoint controlPoint1:ls[2].secondPoint controlPoint2:ls[1].secondPoint];
                        [self.currentPath.path  closePath];

                        lastSegmentOfPrev = ls[3]; // ................. (7)
                    }


                     dispatch_async(dispatch_get_main_queue(), ^{
                            bufIdx = 0;

                            [m_pathArray addObject:self.currentPath];
                            [self setNeedsDisplay];

                        });
                    });


                pts[0] = pts[3];
                pts[1] = pts[4]; 
                ctr = 1;
            }
        }        
}

所以朋友们,请帮帮我。

【问题讨论】:

  • 本文中提到的方法可能对您有用 [Stackoverflow 链接][1] [1]:stackoverflow.com/questions/20853765/…
  • @bhavyakothari,我认为您没有正确阅读我的问题,我遵循了相同的链接,并且我在我的问题中也提到了它

标签: ios uikit core-graphics multi-touch uibezierpath


【解决方案1】:

您需要调试才能确认,但它似乎与您在touchesBegan:withEvent: 中的逻辑有关。在这种方法中,您检查每次有新的触摸以确定它是否是“最高的”,但是当最高的触摸确实发生变化时,您似乎不会中止/重置任何现有的绘图。

您最好的方法可能是使用日志记录来确定“最高”触摸是否/何时发生变化以及这对进行中的生产线有什么影响。

另外,在touchesMoved: 中,您不需要for (UITouch *touch in touches) 循环,因为您已经引用了self.trackingTouch,因此您可以直接使用它。

【讨论】:

  • 您好@Wain,感谢您的回复,我已根据您的建议对代码进行了编辑,我的意思是我正在显示代码,我如何中止任何现有的绘图。我在测试时注意到的一件事是,只有在书写时才会发生这种情况,如果您的两个或多个手指触摸下面的屏幕,如果除了绘图手指之外只有一个手指在触摸,那么它就可以正确书写。
  • 通过查看代码,我猜测通过销毁self.currentPath 并将ctr 重置为零来重新启动您的线条绘制算法。
  • 我什么时候应该这样做?当我获得更高价值的触摸时,在 touchesBegan 中?但我总是在创建一个新的 self.currentPath 或非常 touchesMoved。说啥? @Wain
  • 您将呼叫添加到discardDrawing 的位置。那应该只是取消当前行并开始一个新行。我不知道你的绘图算法或有时间研究它,所以你需要决定当你检测到一个不好的触摸时如何取消当前线......
  • 你好@Wain,如果你检查我上面的代码,我已经在 touchesBegan 中添加了对 dicardDrawing 的调用。您无法查看吗?
【解决方案2】:

如果我正确理解了您的问题,那么每当用户在您的画布上使用多个手指时,您就会出现不希望的笔触。既然你已经有了self.trackingTouch,那么忽略所有不是self.trackingTouch 的触摸是否合理?

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    if (self.trackingTouch)
    {
        // another touch is active so we ignore this one
        return;
    }
    // ...the rest of your code
}

-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = self.trackingTouch;
    if (![touches containsObject:touch])
    {
        // updates to touches other than self.trackingTouch
        return;
    }

    // ...process only self.trackingTouch in the rest of your code
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = self.trackingTouch;
    if (![touches containsObject:touch])
    {
        // updates to touches other than self.trackingTouch
        return;
    }

    // ...process only self.trackingTouch in the rest of your code

   self.trackingTouch = nil;
}

-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    // ...same as touchesEnded:withEvent:
}

【讨论】:

  • 嘿@John 感谢您的回复,我忽略了所有其他触摸,因为在 touchesBegan 中,我正在检查一个条件,并基于此决定跟踪触摸。那么这有什么问题呢?
  • @Ranjit 自发布此问题以来,您是否对代码进行了更新?更新原始帖子可能会有所帮助。
  • @John,我没有做出会改变我原来帖子的重大更改。
  • 你好@John,触摸结束你为什么要让 self.trackingTouch = nil;在 touchesBegan 中你说 if(self.trackingTouch) 然后返回。你能给我解释一下吗
  • 你好@John,请看这个stackoverflow.com/questions/21935064/…
猜你喜欢
  • 1970-01-01
  • 2014-01-12
  • 1970-01-01
  • 1970-01-01
  • 2012-06-13
  • 2015-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多