经常会遇到需求,要求手势的缩放或者旋转操作,要求动作变化围绕某一个特定点,或者是两指的中心点,或者是某一个点。
这个问题首先要清晰的知道,iOS各个view的层次关系。特别是,要清除的知道,当前view的frame与superView的bounds是一个坐标系。
具体来讲,AnchorPoint 是iOS CoreAnimation层的事物。图层的anchorPoint属性是一个CGPoint值,它指定了一个基于图层bounds的符合位置坐标系的位置。Anchor point指定了bounds相对于position的值,更重要的是,它是变换的支点。AnchorPoint值的范围是0 – 1 ,可以理解为AnchorPoint表示了支点位置的坐标占bounds的比例。
iOS CoreAnimation 坐标系原点位于左上角,因此,我们可以很容易的知道,如果想要一个图层的支点位于图层左上角,那么它的AnchorPoint应该是(0, 0)。相应的如果想要支点位于左下角,AnchorPoint应该是 (0, 1)。而默认的中心点的AnchorPoint是(0.5, 0.5)。下图更容易理解。
一、如何设置AnchorPoint?
事实上,如果更改了一个图层的AnchorPoint,那么这个图层会发送位移。原因不表,看看文档便知。问题是发生位移之后,我们怎么将位移修复回来。下面是写的方法。
- (void)setAnchorPoint:(CGPoint)anchorPoint forView:(UIView *)view { CGPoint oldOrigin = view.frame.origin; view.layer.anchorPoint = anchorPoint; CGPoint newOrigin = view.frame.origin; CGPoint transition; transition.x = newOrigin.x - oldOrigin.x; transition.y = newOrigin.y - oldOrigin.y; view.center = CGPointMake (view.center.x - transition.x, view.center.y - transition.y); }
当然你也可以把他写进UIView 的 categary。调用就更方便了。
在进行完围绕AnchorPoint的变换之后,一定要切记将AnchorPoint改回默认。否则有些不需要特殊AnchorPoint的操作,比如拖动,就会变得乱七八糟了。
- (void)setDefaultAnchorPoint forView:(UIView *)view { [self setAnchorPoint:CGPointMake(0.5f, 0.5f) forView:view]; }
OK,以上是我们在知道了AnchorPoint之后,怎么进行AnchorPoint的设置和回归。那么怎么得到我们真正想要的AnchorPoint的值呢?
二、如何获得AnchorPoint?
如果是两指的缩放或者旋转,有以下方法供参考:
/** * Correct UIGestureRecognizer ‘s view ‘s anchor point , make the view scale or rotate correctly. */ - (void)correctAnchorPointBaseOnGestureRecognizer:(UIGestureRecognizer *)gr { CGPoint onoPoint = [gr locationOfTouch:0 inView:gr.view]; CGPoint twoPoint = [gr locationOfTouch:1 inView:gr.view]; CGPoint anchorPoint; anchorPoint.x = (onoPoint.x + twoPoint.x) / 2 / gr.view.bounds.size.width; anchorPoint.y = (onoPoint.y + twoPoint.y) / 2 / gr.view.bounds.size.height; [self setAnchorPoint:anchorPoint forView:gr.view]; }
记得在UIGestureRecongizer 里,当state == UIGestureRecognizerStateBegan 时,进行调用。然后在手势结束或者失败的时候,(Gr.state == UIGestureRecognizerStateEnded || Gr.state == UIGestureRecognizerStateFailed || pinchGr.state == UIGestureRecognizerStateCancelled) ,将Anchor Point回归默认。
如果是比如我需求里所需,要求90度旋转的时候,围绕画布中心而不是视图中心旋转。有如下方法参考
- (void)correctAnchorPointForView:(UIView *)view { CGPoint anchorPoint = CGPointZero; CGPoint superviewCenter = view.superview.center; // superviewCenter是view的superview 的 center 在view.superview.superview中的坐标。 CGPoint viewPoint = [view convertPoint:superviewCenter fromView:view.superview.superview]; // 转换坐标,得到superviewCenter 在 view中的坐标 anchorPoint.x = (viewPoint.x) / view.bounds.size.width; anchorPoint.y = (viewPoint.y) / view.bounds.size.height; [self setAnchorPoint:anchorPoint forView:view]; }
同样记得,变换完毕后,重置 AnchorPoint到默认。
iOS围绕某点缩放或旋转的AnchorPoint的设定