原文出处:
Dariel在杭州(@Dariel在杭州)
一切的动画其实都是假象,3D效果也是这样.本篇我们来做一个这样的特效.
先忽略掉3D效果,我们先要做的是一个右拉的抽屉效果.
总体思路:
1.创建一个ContainerViewController容器控制器,然后把左侧选择菜单的SideMenuViewController,和右侧负责显示内容的MainViewController 添加到ContainerViewController中.
2.给容器控制器ContainerViewController添加一个手势监听,通过修改偏移量完成抽屉效果.
3.设置anchorPoint,给左侧SideMenuViewController的view以及左上角的图片按钮添加3D效果.
如果想知道详情请看代码,我们这边把核心的部分说下:
- 给ContainerViewController添加手势监听,然后在监听方法中该去怎么处理:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
func
handleGesture
(
recognizer
: UIPanGestureRecognizer
)
{
let
translation
=
recognizer
.
translationInView
(
recognizer
.
view
!
.
superview
!
)
// (isOpening ? 1.0 : -1.0) isOpening为BOOL值,表示打开或者关闭
var
progress
=
translation
.
x
/
menuWidth
*
(
isOpening
?
1.0
:
-
1.0
)
// 保证在0~1之间
progress
=
min
(
max
(
progress
,
0
)
,
1.0
)
switch
recognizer
.
state
{
case
.
Began
:
let
isOpen
=
mainVC
.
view
.
frame
.
origin
.
x
/
menuWidth
isOpening
=
isOpen
==
1.0
?
false
:true
// 为layer的效果添加一个缓存,作用是避免旋转的时候产生锯齿
sideMenuVC
.
view
.
layer
.
shouldRasterize
=
true
;
// 设置渲染的范围
sideMenuVC
.
view
.
layer
.
rasterizationScale
=
UIScreen
.
mainScreen
(
)
.
scale
case
.
Changed
:
// 核心代码:调整容器中视图的位置 3D效果 以及透明度 以及左上角按钮的翻转效果
setToPercent
(
isOpening
?
progress
:
(
1.0
-
progress
)
)
case
.
Ended
: fallthrough
case
.
Cancelled
: fallthrough
case
.
Failed
:
// 分页效果
var
targetProgress
: CGFloat
if
(
isOpening
)
{
targetProgress
=
progress
Void
in
self
.
setToPercent
(
targetProgress
)
}
,
completion
:
{
(
_
)
->
Void
in
// 记得关闭layer的缓存渲染
self
.
sideMenuVC
.
view
.
layer
.
shouldRasterize
=
false
}
)
default
: break
}
}
|
- setToPercent方法中的设置:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
func
setToPercent
(
percent
: CGFloat
)
{
// 调整mainVC.view的位置
mainVC
.
view
.
frame
.
origin
.
x
=
menuWidth
*
CGFloat
(
percent
)
// 设置3D效果及透明度
sideMenuVC
.
view
.
layer
.
transform
=
menuTransformForPercent
(
percent
)
sideMenuVC
.
view
.
alpha
=
CGFloat
(
max
(
0.2
,
percent
)
)
// 左上角按钮的翻转设置
let
mainVc
=
(
mainVC
as
!
UINavigationController
)
.
viewControllers
.
first
as
?
MainViewController
if
let
menuButton
=
mainVc
?
.
menuButton
{
menuButton
.
imageView
.
layer
.
transform
=
buttonTransformForPercent
(
percent
)
}
}
|
- 3D效果的核心代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
// 根据百分比添加一个3D特效
func
menuTransformForPercent
(
percent
: CGFloat
)
->
CATransform3D
{
var
identify
=
CATransform3DIdentity
// m34负责z轴方向的translation(移动),m34= -1/D, 默认值是0, D越小透视效果越明显,这边的1000视情况调整的
identify
.
m34
=
-
1.0
/
1000
let
remainingPercent
=
1.0
-
percent
let
angle
=
remainingPercent
*
CGFloat
(
-
M_PI_2
)
// 后面3个数为 x y z
let
rotationTransform
=
CATransform3DRotate
(
identify
,
angle
,
0.0
,
1.0
,
0.0
)
// 将值转换成一个矩阵
let
translationTransform
=
CATransform3DMakeTranslation
(
menuWidth
*
percent
,
0
,
0
)
// 将上面两者结合起来
return
CATransform3DConcat
(
rotationTransform
,
translationTransform
)
}
// 为按钮添加一个3D效果
func
buttonTransformForPercent
(
percent
: CGFloat
)
->
CATransform3D
{
var
identity
=
CATransform3DIdentity
identity
.
m34
=
-
1.0
/
1000
let
angle
=
percent
*
CGFloat
(
-
M_PI
)
let
rotationTransform
=
CATransform3DRotate
(
identity
,
angle
,
1.0
,
1.0
,
0.0
)
return
rotationTransform
}
|
本文整理自 : iOS.Animations.by.Tutorials.v2.0
源码 : https://github.com/DarielChen/DemoCode
如有疑问,欢迎留言 :-D