iOS CAShapeLayer、CADisplayLink 实现波浪动画效果

简介:

效果图

代码已上传 GitHub:htt0p s : / / g i t hu b . c o m/ S il e n ce - G i t H u b /C o r e A n im a t i o n D em o 

可以自定义波浪高度、宽度、速度、方向、渐变速度、水的深度等参数。

实现原理

波浪的形状绘制在 CAShapeLayer 上。通过 CADisplayLink 与屏幕刷新频率同步,每次刷新都绘制新的波浪,并改变小船的位置和角度。另外,水和天空的颜色是渐变的,由 CAGradientLayer 实现,其中,显示水的 CAGradientLayer 需要有波浪形状的 CAShapeLayer 的遮罩(mask)。

CAShapeLayer

CAShapeLayer 的属性 path (CGPath)就是图层要显示的形状。把波浪的形状绘制出来,赋值给此属性即可。

CADisplayLink

创建 CADisplayLink,相应的 target 实现屏幕刷新时要调用的方法。把 CADisplayLink 加入 RunLoop 中。通过 isPaused 属性控制 CADisplayLink 是否暂停(target 是否调用方法)

private var waveLink: CADisplayLink?
waveLink = CADisplayLink(target: self, selector: #selector(waveLinkRefresh))
waveLink?.isPaused = truewaveLink?.add(to: .current, forMode: .defaultRunLoopMode)

绘制波浪

波浪的形状关键是正弦函数曲线

y = A * sin(x + B)

参数 A 决定了波浪的高度;参数 B 决定了波浪在 x 轴的位置。

用一个属性 currentPhase 表示参数 B

private var currentPhase: CGFloat = 0

每次屏幕刷新的时候用 currentPhase 绘制,然后更新此属性,加上一个固定的数。这样波浪就会朝左或右匀速移动。

为了使波浪高度逐渐变化,用一个属性表示参数 A,然后每次绘制后更新此属性,加上一个固定的数,直到波浪高度达到目标值。

小船的位置和旋转角度

已知小船 x 轴坐标,通过正弦函数可以直接计算出小船的 y 轴坐标。此外,小船需要随着波浪旋转,旋转至船底与波浪表面相切。这就要对正弦函数进行求导

y' = A * cos(x + B)

用以上式子计算出小船所在位置的 y',表示正弦函数在此处的切线斜率,几何意义是切线与 x 轴的夹角的正切值。反正切即可求出切线与 x 轴的夹角,也就是小船需要旋转的角度

angle = atan(y')

用以上旋转角度,改变小船视图(UIView)的 transform,调用 CGAffineTransform 的 rotated(by:) 方法,实现小船的旋转。

CAGradientLayer

CAGradientLayer 默认的颜色渐变方向是由上至下。给 colors 属性赋值一个包含 CGColor 的数组,则图层颜色由上至下,从数组第一个值经中间值渐变至最后一个值。

显示水的 CAGradientLayer 需要呈现波浪形状,需要 CAShapeLayer 的遮罩。把绘制好波浪形状的 CAShapeLayer 赋值给 CAGradientLayer 的 mask 属性即可。

以上是动画效果的实现原理,具体见 Git H u b: h t t ps : / / gi t h u b. c o m / S i l e nc e - G i tH u b / C or e A n im a t i o n De m o 

转载请注明出处:ht tp :/ / w w w .c n b l og s .c o m /s i l en c e -c n b l og s /p / 6 97 9 4 1 8 .h t m l















本文转自xmgdc51CTO博客,原文链接: http://blog.51cto.com/12953214/1940544,如需转载请自行联系原作者



相关文章
|
安全 数据安全/隐私保护 iOS开发
iOS小技能:【发红包】使用tweak和lua脚本结合进行实现
我们开发的大部分越狱程序,都是编译成动态链接库(`例如:介绍的越狱程序(Tweak)开发,就是动态链接库。`),然后通过越狱平台的MobileSubstrate(iOS7上叫CydiaSubstrate)来加载进入目标程序(Target),通过对目标程序的挂钩(Hook),来实现相应的功能。
262 0
|
存储 API iOS开发
iOS UIView动画效果
iOS UIView动画效果
|
移动开发 JavaScript weex
weex-自定义module,实现weex在iOS的本地化,js之间互相跳转,交互,传值(iOS接入weex的最佳方式)
weex-自定义module,实现weex在iOS的本地化,js之间互相跳转,交互,传值(iOS接入weex的最佳方式)
219 0
|
存储 数据处理 iOS开发
iOS开发-本地推送实现方法和数据处理方案(二)
iOS开发-本地推送实现方法和数据处理方案(二)
168 0
|
存储 数据处理 iOS开发
iOS开发-本地推送实现方法和数据处理方案(一)
iOS开发-本地推送实现方法和数据处理方案(一)
209 0
|
iOS开发
iOS开发 - 不通过import引入类名实现push或present
iOS开发 - 不通过import引入类名实现push或present
75 0
|
Android开发 iOS开发
iOS开发 - 商品详情页两种分页模式,只提供思路和实现方式。
iOS开发 - 商品详情页两种分页模式,只提供思路和实现方式。
354 0
iOS开发 - 商品详情页两种分页模式,只提供思路和实现方式。
|
存储 安全 iOS开发
iOS开发 - 继udid,Mac地址等一系列唯一标识无效后,如何用KeyChain来实现设备唯一性
iOS开发 - 继udid,Mac地址等一系列唯一标识无效后,如何用KeyChain来实现设备唯一性
398 0
iOS开发 - 继udid,Mac地址等一系列唯一标识无效后,如何用KeyChain来实现设备唯一性
|
Swift 数据安全/隐私保护 iOS开发
iOS开发 - swift通过Alamofire实现https通信
iOS开发 - swift通过Alamofire实现https通信
346 0
iOS开发 - swift通过Alamofire实现https通信
|
开发者 iOS开发
iOS开发 - 用AFNetworking实现https单向验证,双向验证
iOS开发 - 用AFNetworking实现https单向验证,双向验证
342 0
iOS开发 - 用AFNetworking实现https单向验证,双向验证