我在UIView中使用CoreGraphics绘制图形,我希望能够使用触摸输入与图形进行交互。由于触摸是在设备坐标中接收的,我需要将其转换为用户坐标以便将其与图形相关联,但这已经成为障碍,因为CGContextConvertPointToUserSpace
在图形绘制上下文之外不起作用。
这是我尝试过的。
在drawRect:
CGContextScaleCTM(ctx,...);
CGContextTranslateCTM(ctx,...); // transform graph to fit the view nicely
self.ctm = CGContextGetCTM(ctx); // save for later
// draw points using user coordinates
在我的触摸事件处理程序中:
CGPoint touchDevice = [gesture locationInView:self]; // touch point in device coords
CGPoint touchUser = CGPointApplyAffineTransform(touchDevice, self.ctm); // doesn't give me what I want
// CGContextConvertPointToUserSpace(touchDevice) <- what I want, but doesn't work here
使用ctm的反转也不起作用。我承认我无法理解设备坐标,用户坐标和转换矩阵之间的含义和关系。我认为这并不像我想要的那么简单。
编辑:Apple文档的一些背景信息(iOS Coordinate Systems和Drawing Model)。
“窗口的位置和大小均为屏幕坐标,由显示器的坐标系定义。”
“绘图命令引用固定比例的绘图空间,称为用户坐标空间。操作系统将此绘图空间中的坐标单位映射到相应目标设备的实际像素上。 “
“您可以通过修改当前变换矩阵(CTM)来更改视图的默认坐标系.CTM将视图坐标系中的点映射到设备屏幕上的点。”
答案 0 :(得分:0)
我发现CTM 已经包含了一个转换,用于将视图坐标(左上角的原点)映射到屏幕坐标(带有来自左下角)。所以(0,0)被转换为(0,800),其中我的视图高度为800,(0,2)映射到(0,798)等。所以我收集了我们正在谈论的3个坐标系:< strong>屏幕坐标,查看/设备坐标,用户坐标。 (如果我错了,请纠正我。)
CGContext变换(CTM)从用户坐标一直映射到屏幕坐标。我的解决方案是分别维护我自己的变换,从用户坐标到视图坐标。然后我可以用它从视图坐标返回用户坐标。
我的解决方案:
在drawRect:
CGAffineTransform scale = CGAffineTransformMakeScale(...);
CGAffineTransform translate = CGAffineTransformMakeTranslation(...);
self.myTransform = CGAffineTransformConcat(translate, scale);
// draw points using user coordinates
在我的触摸事件处理程序中:
CGPoint touch = [gesture locationInView:self]; // touch point in view coords
CGPoint touchUser = CGPointApplyAffineTransform(touchPoint, CGAffineTransformInvert(self.myTransform)); // this does the trick
替代解决方案:
另一种方法是手动设置相同的上下文,但我认为这更像是一种黑客攻击。
在我的触摸事件处理程序中:
#import <QuartzCore/QuartzCore.h>
CGPoint touch = [gesture locationInView:self]; // view coords
CGSize layerSize = [self.layer frame].size;
UIGraphicsBeginImageContext(layerSize);
CGContextRef context = UIGraphicsGetCurrentContext();
// as in drawRect:
CGContextScaleCTM(...);
CGContextTranslateCTM(...);
CGPoint touchUser = CGContextConvertPointToUserSpace(context, touch); // now it gives me what I want
UIGraphicsEndImageContext();