Swift CAShapeLayerで図形にグラデーションをつける方法
UIViewにCAShapeLayerを补充し図形を表示できる。CAShapeLayerのプロパティには,fillColor(背景を涂る色指定)やstrokeColor(図形の轮郭を书く时の色指定)が用意されているので,简単に図形に色を涂ることができる。
ではCAShapeLayerで背景色にグラデーションショ场合はどうするのか?
毎回忘れるのと误解していたので整理がてらメモ。
CALayerの面膜
ayラデーションを付ける前にCALayerのmaskの机能を见てみる。
口罩— CALayer | Apple开发人员文档
var mask: CALayer? { get set }
を,别のCALayerを面具にセットすると,もともとのCAlayerの図形が「マスク」され部分的に表示されるという机能である。
面具サンプル
赤い星のCAShapeLayerに黒丸4つのCAShapeLayerをmaskとして设定すると,星の一部が切り抜かれて表示される。
黒丸4つのマスクと重なった部分が表示されたのだ。
如Swiftコード。
- 黒丸マスクCAShapeLayer
// mask path
let maskpath = CGMutablePath()
maskpath.addEllipse(in: CGRect(x: 10, y: 10, width:30, height:30))
maskpath.addEllipse(in: CGRect(x: 10, y: 60, width:30, height:30))
maskpath.addEllipse(in: CGRect(x: 60, y: 10, width:30, height:30))
maskpath.addEllipse(in: CGRect(x: 60, y: 60, width:30, height:30))
// show path on layer
let maskLayer = CAShapeLayer()
maskLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
maskLayer.path = maskpath
maskLayer.fillColor = UIColor.black.cgColor
- 星マスクCAShapeLayer
// create path of ☆
let starPath = CGMutablePath()
starPath.move(to: CGPoint(x:19.098,y:100))
starPath.addLine(to: CGPoint(x:25,y:63.82))
starPath.addLine(to: CGPoint(x:-0,y:38.197))
starPath.addLine(to: CGPoint(x:34.549,y:32.918))
starPath.addLine(to: CGPoint(x:50,y:-0))
starPath.addLine(to: CGPoint(x:65.451,y:32.918))
starPath.addLine(to: CGPoint(x:100,y:38.197))
starPath.addLine(to: CGPoint(x:75,y:63.82))
starPath.addLine(to: CGPoint(x:80.902,y:100))
starPath.addLine(to: CGPoint(x:50,y:82.918))
starPath.closeSubpath()
// show path on layer
let shapeLayer = CAShapeLayer()
shapeLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
shapeLayer.path = starPath
shapeLayer.strokeColor = UIColor.red.cgColor
shapeLayer.lineWidth = 2
shapeLayer.fillColor = UIColor.red.cgColor
shapeLayer.borderColor = UIColor.gray.cgColor
- 星マスクに黒丸マスクをつけてUIViewに表示
shapeLayer.mask = maskLayer
view.layer.addSublayer(shapeLayer)
アニメーションする面具
今度はさっきの赤い星に,アニメーションする円をmaskとして指定してみよう。
期待通り,星型と円が重なるものがアニメーション表示された。
- アニメーションする円のSwiftコード
// mask path
let maskpath = CGMutablePath()
maskpath.addEllipse(in: CGRect(x: 50, y: 50, width: 0, height: 0))
let maskpath2 = CGMutablePath()
maskpath2.addEllipse(in: CGRect(x: 0, y: 0, width: 100, height: 100))
let maskLayer = CAShapeLayer()
maskLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
maskLayer.path = maskpath
maskLayer.fillColor = UIColor.black.cgColor
// アニメーション指定
let pathKeyframe = CAKeyframeAnimation(keyPath: "path")
pathKeyframe.values = [maskpath,maskpath2,maskpath]
pathKeyframe.keyTimes = [0, 0.5, 1]
pathKeyframe.duration = 3.0
pathKeyframe.repeatDuration = CFTimeInterval.infinity
pathKeyframe.isRemovedOnCompletion = false
maskLayer.add(pathKeyframe, forKey: "path")
それで,図形にグラデーションをつける方法は?
グラデーションを描くCAGradientLayerというCALayerがある。そのCAGradientLayerのmaskに希望する形のCALayerを指定すればよいのだ。
CAGradientLayerでグラデーション描くとこうなった。
- CAGradientLayerグラデーションのSwiftコード
let gradLayer = CAGradientLayer()
gradLayer.frame = CGRect(x: 0, y: 0, width: 100, height: 100)
gradLayer.colors = [
UIColor.red.cgColor,
UIColor.blue.cgColor,
]
view.layer.addSublayer(gradLayer)
しちゃえばよさそう,このグラデーションをマスクしちゃえばよさそう。
gradLayer.mask = maskLayer
何を勘违いしていたか
作画ソフトを使うと図形にグラデーションショとうイうイメージなので,CAShapeLayerにグラデーションション用用用ロパティがあるかと思っていました…グラデーションをマスクするのですね。どうもこのあたりに违和感がありましたが,きちんと调べたら理解できました。
もちろんCALayerやUIViewを自前で描画する方法もあると思いますが,一例として。
参考
- 口罩— CALayer | Apple开发人员文档
- CAShapeLayer —核心动画| Apple开发人员文档
- CAGradientLayer —核心动画| Apple开发人员文档