2014.01.08
经常会遇到需求,要求手势的缩放或者旋转操作,要求动作变化围绕某一个特定点,或者是两指的中心点,或者是某一个点。
这个问题首先要清晰的知道,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)。下图更容易理解。
![Snip20140108_2](http://chentoo.com/wp-content/uploads/2014/01/Snip20140108_2.png)
一、如何设置AnchorPoint?
事实上,如果更改了一个图层的AnchorPoint,那么这个图层会发送位移。原因不表,看看文档便知。问题是发生位移之后,我们怎么将位移修复回来。下面是写的方法。
1
2
3
4
5
6
7
8
9
10
11
12
|
-
(
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?
如果是两指的缩放或者旋转,有以下方法供参考:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
/**
* 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度旋转的时候,围绕画布中心而不是视图中心旋转。有如下方法参考
1
2
3
4
5
6
7
8
9
10
11
12
|
-
(
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到默认。