从触摸点获取单个像素

时间:2012-04-04 16:53:16

标签: objective-c ios cocoa-touch touch multi-touch

是否可以检测到每个被触摸的像素?更具体地,当用户触摸屏幕时,是否可以跟踪用户触摸的点群集的所有x-y坐标?如何区分用户使用拇指绘图以及何时使用手指绘图?我想根据用户触摸屏幕的方式反映画笔差异,并且还想跟踪所有被触摸的像素。

我目前正在使用Apple开发者网站的GLPaint示例中的以下代码:

http://developer.apple.com/library/ios/#samplecode/GLPaint/Introduction/Intro.html

示例代码允许使用预定义的画笔大小进行绘制,并沿途跟踪x-y坐标。如何根据用户触摸屏幕的方式更改画笔并跟踪随时间触摸的所有像素?

// Drawings a line onscreen based on where the user touches

- (void) renderLineFromPoint:(CGPoint)start toPoint:(CGPoint)end

{
     NSLog(@"x:%f   y:%f",start.x, start.y);

     static GLfloat*          vertexBuffer = NULL;

     static NSUInteger     vertexMax = 64;

     NSUInteger               vertexCount = 0,

                    count,

                    i;



     [EAGLContext setCurrentContext:context];

     glBindFramebufferOES(GL_FRAMEBUFFER_OES, viewFramebuffer);



     // Convert locations from Points to Pixels

     CGFloat scale = self.contentScaleFactor;

     start.x *= scale;

     start.y *= scale;

     end.x *= scale;

     end.y *= scale;



     // Allocate vertex array buffer

     if(vertexBuffer == NULL)

          vertexBuffer = malloc(vertexMax * 2 * sizeof(GLfloat));



     // Add points to the buffer so there are drawing points every X pixels

     count = MAX(ceilf(sqrtf((end.x - start.x) * (end.x - start.x) + (end.y - start.y) * (end.y - start.y)) / kBrushPixelStep), 1);

     for(i = 0; i < count; ++i) {

          if(vertexCount == vertexMax) {

               vertexMax = 2 * vertexMax;

               vertexBuffer = realloc(vertexBuffer, vertexMax * 2 * sizeof(GLfloat));

          }



          vertexBuffer[2 * vertexCount + 0] = start.x + (end.x - start.x) * ((GLfloat)i / (GLfloat)count);

          vertexBuffer[2 * vertexCount + 1] = start.y + (end.y - start.y) * ((GLfloat)i / (GLfloat)count);

          vertexCount += 1;

     }



     // Render the vertex array

     glVertexPointer(2, GL_FLOAT, 0, vertexBuffer);

     glDrawArrays(GL_POINTS, 0, vertexCount);



     // Display the buffer

     glBindRenderbufferOES(GL_RENDERBUFFER_OES, viewRenderbuffer);

     [context presentRenderbuffer:GL_RENDERBUFFER_OES];

}


// Handles the start of a touch

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

{

     CGRect                    bounds = [self bounds];

     UITouch*     touch = [[event touchesForView:self] anyObject];

     firstTouch = YES;

     // Convert touch point from UIView referential to OpenGL one (upside-down flip)

     location = [touch locationInView:self];

     location.y = bounds.size.height - location.y;

}

// Handles the continuation of a touch.

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

{  

     CGRect                    bounds = [self bounds];

     UITouch*               touch = [[event touchesForView:self] anyObject];



     // Convert touch point from UIView referential to OpenGL one (upside-down flip)

     if (firstTouch) {

          firstTouch = NO;

          previousLocation = [touch previousLocationInView:self];

          previousLocation.y = bounds.size.height - previousLocation.y;

     } else {

          location = [touch locationInView:self];

         location.y = bounds.size.height - location.y;

          previousLocation = [touch previousLocationInView:self];

          previousLocation.y = bounds.size.height - previousLocation.y;

     }



     // Render the stroke

     [self renderLineFromPoint:previousLocation toPoint:location];

}



// Handles the end of a touch event when the touch is a tap.

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

     CGRect                    bounds = [self bounds];

    UITouch*     touch = [[event touchesForView:self] anyObject];

     if (firstTouch) {

          firstTouch = NO;

          previousLocation = [touch previousLocationInView:self];

          previousLocation.y = bounds.size.height - previousLocation.y;

          [self renderLineFromPoint:previousLocation toPoint:location];

     }

}


// Handles the end of a touch event.

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event

{

     // If appropriate, add code necessary to save the state of the application.

     // This application is not saving state.

}

2 个答案:

答案 0 :(得分:1)

AFAIK没有API可以访问触摸区域进行触摸。我不确定,考虑到电容式触摸屏的限制,你想要的是否在物理上是可能的。我记得在最近的Cocoa Heads上的演示文稿,其中证明了OS X(通过私有API)可用于触控板的一些信息,但不适用于iOS。

我认为这是图形平板电脑采用内置传感器技术的特殊触控笔的原因之一。

对于绘图应用程序,部分解决方法可能是模拟某些桌面应用程序执行的“墨水”:如果用户的触摸在给定位置中徘徊,则绘制就好像墨水从“笔”中出来并逐渐扩散通过“纸张”。

答案 1 :(得分:1)

iPad中的Broadcomm硬件以64 Hz扫描屏幕。它通过在构成触摸屏电极的39个透明导电层上连续放置400μs的信号来实现这一点。如果您的手指在0.015625秒内移动超过一个像素距离,这可能是硬件无法检测到这一点,因为它正忙于测量屏幕的其他部分以获得更多触摸事件。

无论iOS还是Android,这都是一样的。便宜的Android平板电脑和大屏幕的扫描速度都有所降低,因此它们的触摸事件间隔更大。

Wacom平板电脑以100 Hz的频率运行数字转换器,因此点序列将更精细,但仍会错过触控笔在两次测量之间接触的像素。