我建议您采取不同的方法。不要不断创建新图像以放入您的UIImageView。相反,请像这样设置视图层次结构:
White view
"Hole" view (just a regular UIView)
Image view
也就是说,白色视图将孔视图作为子视图。孔视图将UIImageView 作为其子视图。
孔视图必须将其clipsToBounds 属性设置为YES(您可以使用代码或在您的笔尖中设置它)。
图像视图的大小应设置为其图像的大小。这当然会大于孔视图的大小。
这非常重要:图像视图的中心必须设置为孔视图的中心。
这是我在测试项目中用于设置的代码。白色视图是self.view。我从以白色视图为中心的孔开始,并将图像视图的中心设置为孔视图的中心。
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:YES];
CGRect bounds = self.view.bounds;
self.holeView.center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
self.holeView.clipsToBounds = YES;
bounds = self.holeView.bounds;
self.imageView.center = CGPointMake(CGRectGetMidX(bounds), CGRectGetMidY(bounds));
self.imageView.bounds = (CGRect){ CGPointZero, self.imageView.image.size };
}
我还将图像视图的大小设置为其图像的大小。您可能希望将其设置为白色视图的大小。
要平移和旋转孔,我将设置holeView.transform。我不会更改holeView.frame 或holeView.center。我有两个实例变量_holeOffset 和_holeRotation,用于计算转换。让它看起来像一个穿过白色视图的洞并显示图像视图的技巧是对图像视图应用 inverse 变换,撤消洞视图变换的效果:
- (void)updateTransforms {
CGAffineTransform holeTransform = CGAffineTransformIdentity;
holeTransform = CGAffineTransformTranslate(holeTransform, _holeOffset.x, _holeOffset.y);
holeTransform = CGAffineTransformRotate(holeTransform, _holeRotation);
self.holeView.transform = holeTransform;
self.imageView.transform = CGAffineTransformInvert(holeTransform);
}
这种在子视图上使用逆变换的技巧只有在子视图的中心位于其父视图的中心时才有效。 (从技术上讲,锚点必须对齐,但默认情况下,视图的锚点是它的中心。)
我在holeView 上添加了UIPanGestureRecognizer。我将其配置为将panGesture: 发送到我的视图控制器:
- (IBAction)panGesture:(UIPanGestureRecognizer *)sender {
CGPoint offset = [sender translationInView:self.view];
[sender setTranslation:CGPointZero inView:self.view];
_holeOffset.x += offset.x;
_holeOffset.y += offset.y;
[self updateTransforms];
}
我还在holeView 上添加了UIRotationGestureRecognizer。我将其配置为将rotationGesture: 发送到我的视图控制器:
- (IBAction)rotationGesture:(UIRotationGestureRecognizer *)sender {
_holeRotation += sender.rotation;
sender.rotation = 0;
[self updateTransforms];
}