iOS CAShapeLayer、CADisplayLink 實現波浪動畫效果 效果圖 代碼已上傳 GitHub:https://github.com/Silence GitHub/CoreAnimationDemo 可以自定義波浪高度、寬度、速度、方向、漸變速度、水的深度等參數。 實現原理 波浪的 ...
iOS CAShapeLayer、CADisplayLink 實現波浪動畫效果
效果圖
代碼已上傳 GitHub:https://github.com/Silence-GitHub/CoreAnimationDemo
可以自定義波浪高度、寬度、速度、方向、漸變速度、水的深度等參數。
實現原理
波浪的形狀繪製在 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 = true
waveLink?.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 屬性即可。
以上是動畫效果的實現原理,具體見 GitHub:https://github.com/Silence-GitHub/CoreAnimationDemo
轉載請註明出處:http://www.cnblogs.com/silence-cnblogs/p/6979418.html