今天在开发时候,我封装了一个具有uiview所有操作响应的类别,但是获取最后的经过处理的图像数据时候,发现坐标变成转换后的坐标全映射,也就是变大或者变小了。
分析很明显,坐标转换不对
不认识该状态自己科普:CGAffineTransformIsIdentity
该状态下:
//位置等于中心点的位置减去视图尺寸乘以锚点的值。
UIview
self.origin.x = self.center.x - self.bounds.size.width * self.layer.anchorPoint.x;
retValue.origin.y = self.center.y - self.bounds.size.height * self.layer.anchorPoint.y;
//尺寸等于视图的尺寸
retValue.size.width = self.bounds.size.width;
retValue.size.height = self.bounds.size.height;
首选需要认识一下,frame 与 layer两个概念,另外,对应坐标名称关系
UIView | CALayer |
---|---|
frame | frame |
center | position |
bounds | bounds |
transform | affineTransform |
当一个视图设置了非CGAffineTransformIdentity的仿射变化值后,我们不能再通过设置frame属性的值来修改视图的位置和尺寸了,否则最终展示的效果圣经病一样。
因为,原理如下,变换前:
self.center.x = frame.origin.x + self.bounds.size.width * self.layer.anchorPoint.x;
self.center.y = frame.origin.y + self.bounds.size.height * self.layer.anchorPoint.y;
self.bounds.size.width = frame.size.width;
self.bounds.size.height = frame.size.height;
如果需要调整视图的位置和尺寸时我们需要操作的是center属性和bounds属性而不能再操作frame属性了
//假设视图尺寸由原来的(width_ori, height_ori)改变为(width_dst, height_dst)那么正确代码应该如下设置:
//尺寸直接设置。
self.view.bounds.size = CGSizeMake(width_dst, height_dst);
//位置需要调整
self.view.center.x += (width_dst - width_ori) * self.view.layer.anchorPoint.x;
self.view.center.y += (height_dst - height_ori) * self.view.layer.anchorPoint.y;
//假设视图位置由原来的(x0,y0)改为(x1,y1)那么正确的代码应该如下设置:
self.view.center.x = x1 + self.view.bounds.size.width * self.view.layer.anchorPoint.x;
self.view.center.y = y1 + self.view.bounds.size.height * self.view.layer.anchorPoint.y;
另外移动时候,互相影响:
默认的anchorPoint是(0.5, 0.5),位于layer的中间,position也是位于layer的中间,layer以中心点为定位点,此时positon的意义是 layer的中心点距离父layer的原点的位置是position.x,position.y ,所以最终的frame位置如图所示为 {{100, 100}, {100, 100}}
anchorPoint是(1, 1),位于layer的右下角,position也是位于layer的右下角,layer以右下角为定位点,此时positon的意义是 layer的右下角距离父layer的原点的位置是position.x,position.y ,所以最终的frame位置如图所示为 {{50, 50}, {100, 100}}
旋转时候关系
通过公式计算结果;
另外一种思路,借助旋转layer,恢复回去,映射坐标的方式实现。