はじめに
今回は使い所は限られるとは思いますが、虹色ボーダーラインのアニメーションを実装します。
こんな感じ↓
Swiftで虹色のボーダーラインのアニメーション pic.twitter.com/tzrhSnnebS
— M (@p_x9) April 18, 2021
本編
1. 虹色のCGColor配列を作成
虹色の配列を作成します。色相、彩度、明度のうち、色相を少しずつ変化させればなだらかな虹色が作成できます。
後々のためここではUIColorではなくCGColorの配列としておきます。
var rainbow: [CGColor] {
let increment: CGFloat = 0.02
return [CGFloat](stride(from: 0.0, to: 1.0, by: increment)).map{ hue in
UIColor(hue: hue, saturation: 1.0, brightness: 1.0, alpha: 1.0).cgColor
}
}
2. 虹色のグラデーションを作成する
まず虹色のグラデーションのレイヤを作成します。
グラデーションのレイヤを作成するにはCAGradientLayer
を使います。
ここでCAGradientLayer
のcolorsプロパティに先ほど作成した虹色の配列を適用することで、虹色グラデーションのレイヤができます。
let gradientLayer = CAGradientLayer()
gradientLayer.colors = rainbow
今回はラベルに虹色のボーダーラインアニメーションを追加しますが、そのフレームに対し少しマージンを取ります。
gradientLayer.frame = CGRect(x: -4, y: -4, width: label.frame.width+8, height: label.frame.height+8)
グラデーションの始まりと終わりのポイントを指定します。
今回は左上から右下にかけてのグラデーションにしたいので、以下のように設定しました。この時、x,yともに0から1の範囲で指定する必要があるので注意が必要です。
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer.endPoint = CGPoint(x: 1.0, y: 1.0)
3. アニメーションを行うレイヤの作成
CAShapeLayer
を使用します。
まずボーダラインのpathを指定します。
let shapeLayer = CAShapeLayer()
let path = UIBezierPath(rect: CGRect(x: 0, y: 0, width: label.frame.width+8, height: label.frame.height+8))
shapeLayer.path = path.cgPath
またfillColor
は透明にしておきます。線の太さも決めておきます。
shapeLayer.fillColor = UIColor.clear.cgColor
shapeLayer.lineWidth = 8.0
4. maskの設定
グラデーションのレイヤにmaskとして3で作成したアニメーションを行うレイヤを設定します。
四角いグラデーションのレイヤから、maskに設定したレイヤによってくり抜くといったイメージです。
5. レイヤをviewに適用
今回はlabelに対して設定します。
label.layer.addSublayer(shapeLayer)
アニメーションの作成
CABasicAnimation
を使用します。CAShapeLayerのstrokeEndプロパティを0から1までアニメーションさせたいので以下のように実装します。
また、アニメーションの時間も設定しておきます。
let animation = CABasicAnimation(keyPath: #keyPath(CAShapeLayer.strokeEnd))
animation.fromValue = 0.0
animation.toValue = 1.0
animation.duration = 3.0
ここではアニメーションを無限にループさせたいので以下のように設定しておきます。
animation.repeatDuration = .infinity
6. animationのレイヤへの適用
以下を実行するとアニメーションが始まります。
self.shapeLayer.add(animation, forKey: #keyPath(CAShapeLayer.strokeEnd))
7.完成
これで完成です。
動作原理
まず、CAGradientLayer
でグラデーションのレイヤを作ります。
mask
プロパティに別レイヤを設定すると、設定したレイヤの形にくり抜くことができます。
そこで、CAShapeLayer
で外枠となる部分のレイヤを作成し、mask
として適用することでグラデーションの外枠ができます。
CAShapeLayer
のstrokeStart
とstrokeEnd
が外枠の始まりと終わりの部分を表すのでこと値をアニメーションで徐々に変化させることで、外枠がアニメーションし目的を達成することができます。
おわりに
読んでいただいてありがとうございます。初めて二日連続で記事を書きました。参考になれれば嬉しいです。
ご指摘ご質問等ございましたら、コメントまたはDMまでお願いします。
本記事での内容はこちらのリポジトリよりダウンロードできます。
簡単に実行できるので良かったら試してみてください
追記
2021/04/19
この記事に関連した記事を書きました。
合わせて読んでいただけると嬉しいです
https://qiita.com/p_x9/items/5fbe76748ee060f18daa