你将如何检测只能在非透明像素触摸UIImageView
,有效?
考虑像下面的一个,并显示图像UIImageView
。 我们的目标是是使手势识别器仅当触摸发生在非透明(黑色在这种情况下)的图像的区域响应。
思路
- 覆盖
hitTest:withEvent:
或pointInside:withEvent:
,虽然这种方法可能是非常低效的,因为这些方法获得的触摸事件中调用多次。 - 检查如果一个像素是透明的可能会产生意想不到的效果,如手指大于一个像素。 检查周围的命中点像素的圆形区域,或试图找到一个透明的道路走向的边缘可能会更好地工作。
奖金
- 它会是不错的图像的外周和内透明的像素之间进行区分。 在该实例中,零内部的透明的像素也应视为有效。
- 如果图像已经变换,会发生什么?
- 可在图像处理进行硬件加速?
这是我的快速实施:(基于检索的一个UIImage一个像素的α值 )
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
//Using code from https://stackoverflow.com/questions/1042830/retrieving-a-pixel-alpha-value-for-a-uiimage
unsigned char pixel[1] = {0};
CGContextRef context = CGBitmapContextCreate(pixel,
1, 1, 8, 1, NULL,
kCGImageAlphaOnly);
UIGraphicsPushContext(context);
[image drawAtPoint:CGPointMake(-point.x, -point.y)];
UIGraphicsPopContext();
CGContextRelease(context);
CGFloat alpha = pixel[0]/255.0f;
BOOL transparent = alpha < 0.01f;
return !transparent;
}
这是假设该图像是在同一个坐标空间的point
。 如果缩放的推移,你可能要在转换point
检查的像素数据之前。
似乎很快上班对我来说。 我约测量。 0.1-0.4毫秒调用此方法。 它不会做的内部空间,而且可能不是最优的。
在GitHub上,你可以找到一个由OLE Begemann项目延伸UIButton
,使其仅检测触摸其中按钮的图片不是透明的。
由于UIButton
是子类UIView
,它适应UIImageView
应该直截了当。
希望这可以帮助。
好吧,如果你需要做的真快,你需要预先计算的面具。
以下是如何提取它:
UIImage *image = [UIImage imageNamed:@"some_image.png"];
NSData *data = (NSData *) CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
unsigned char *pixels = (unsigned char *)[data bytes];
BOOL *mask = (BOOL *)malloc(data.length);
for (int i = 0; i < data.length; i += 4) {
mask[i >> 2] = pixels[i + 3] == 0xFF; // alpha, I hope
}
// TODO: save mask somewhere
或者你可以使用1x1位图背景的解决方案预先计算的面具。 有一个面具意味着你可以通过任何一点与一个索引内存访问的成本。
作为用于检查大面积大于一个像素 - 我会检查与触摸点中心的圆形像素。 圆上关于16分就足够了。
还检测内像素:另一个预计算一步 - 你需要找到面罩的凸包。 你可以这样做,使用“格雷厄姆扫描”算法http://softsurfer.com/Archive/algorithm_0109/algorithm_0109.htm然后要么填补这一区域的面具,或保存多边形和使用点在多边形测试来代替。
最后,如果图像的变换,你需要转换从屏幕空间的点坐标图像空间,然后你可以检查预先计算的面具。