tvOS视差按钮的ObjC实现
介绍
苹果在最新发布的Apple TV里引入了有趣的图标设计
具体说来 图标由2-5个分层图层构成 在图标被选中的时候 图标内每个图层进行不同幅度的位移 从而形成视觉上具有深度距离感的视差效果 图标构成和效果可以见视频:
这种效果很适合用于多媒体类应用 例如图书或者电影封面 让封面变得立体生动 然而这种效果目前只能在Apple TV的tvOS里见到
所以 如何在iOS上做出同样的效果呢?现在就让我们一起研究下视差按钮的实现原理 并且自己实现一个吧 ^_^
原理
假设我们已经有了以下图片:(你可以从下载链接下载已经分层的四张图片)
1. 总图层在旋转 但不同于一般在屏幕平面上的旋转 而是相对屏幕具有一定夹角的旋转
如果不太了解这种旋转是怎么发生的 我们可以看一张有关 CATransform3D 的图:
1
|
CATransform3D CATransform3DMakeRotation (
|
2.除去旋转 每个图层都在进行不同半径的圆周移动
为什么有移动?
透视是创造三维深度感觉的关键 而透视效果最直白的话来说 就是“近大远小”
让我们来看个例子吧 :-)
3.总的图层也会移动
看到我们刚才那个简陋的效果了没?你有可能会想 为什么看起来和tvOS差别那么大?
原因是 tvOS实现的效果 整个按钮并没有明显地移动 而是近似于固定在某个位置的 这么一来 就要求我们在分图层移动的时候 总图层叠加一项反方向的移动 保证按钮固定住
于是我们又用 Principle 做了一个原型 大体效果应该是这个样子的
4.高光的移动方向恰好相反
高光就是我们在tvOS的图标上看到的白色反光 这个部分其实很简单:
用PS画一个白色的圆 加上模糊效果 就是一个 高光图层
让图层在移动的时候于其他图层方向相反 即让图层叠加之后的效果为 高光永远在离我们最近的地方 这里说起来会有点困惑 但是用代码实现的时候就自然明白了 ^_^
实现
注:实现部分限于篇幅 不可能将所有代码都粘贴出来 只是在几个关键的地方粘贴出来加以说明
完整代码见 https://github.com/JustinFincher/JZtvOSParallaxButton
1.按钮基本
按照我们的计划 这个按钮默认并没有三维效果 就是很多UIImage叠加起来 只有当我们长按的时候 才会有各种旋转和移动
这里动画方式分为两种 第一种是自动动画 首先会移动和旋转到一个特定的角度 然后便开始周期移动了 第二种是手动动画 按钮会跟随手指Drag进行旋转和移动
让我们先新建一个UIButton吧 :-)
1
|
//JZParallaxButton.h
|
1
|
//JZParallaxButton.m
|
写一个自己的init方法 然后在里面加入长按的手势判断
1
|
//JZParallaxButton.m
|
1
|
//JZParallaxButton.m
|
2.层级关系和逻辑判断
1
|
ParallaxButton:UIButton //我们建立的UIButton SubClass
|
有的同学有可能会觉得 为什么需要总视图这个 BoundsView
呢 直接将所有的UIImageView都划归为UIButton的SubView不就好了么?
实验过直接将UIImageView添加到UIButton为SubView后 我有一个相对合理的解释:
我们之前分析原理的时候 说明其实是只有总图层(即 BoundsView
)在旋转的 分图层只需处理移动问题
如果去除了总图层 就只能让每个分图层(即 LayerImageView
)在移动的同时都旋转 这势必带来一个问题 那就是会有“厚度”的感觉
让我们实验下 如果层级关系如下图 会是什么结果
1
|
//JZParallaxButton.h
|
1
|
//JZParallaxButton.m |