0
放射状のグラデーションを描画するカスタムCALayerがあります。アニメーション中以外は素晴らしい作品です。あなたはCABasicAnimation
は、層の新しいコピーを作成していることがわかり、上のスクリーンショットでCABasicAnimationはCALayerの空のデフォルト値のコピーを作成します
:CABasicAnimation
の各反復は、新しいプロパティの空、デフォルト値でCALayer
サブクラスのコピーを作成しているようですgradientOrigin
を更新していますが、その他のプロパティはありません。
これは、アニメーション中に何も描画しないという結果をもたらします。
let animation = CABasicAnimation(keyPath: "gradientOrigin")
animation.duration = 2
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
let newOrigin: CGPoint = CGPoint(x: 0, y: triangle.bounds.height/2)
animation.fromValue = NSValue(CGPoint: triangle.gradientLayer.gradientOrigin)
animation.toValue = NSValue(CGPoint: newOrigin)
triangle.gradientLayer.gradientOrigin = newOrigin
triangle.gradientLayer.addAnimation(animation, forKey: nil)
ここ
カスタムCALayerのコードです:
アニメーションコードです:
ここのようになるはずです何:ここではGIFです
enum RadialGradientLayerProperties: String {
case gradientOrigin
case gradientRadius
case colors
case locations
}
class RadialGradientLayer: CALayer {
var gradientOrigin = CGPoint() {
didSet { setNeedsDisplay() }
}
var gradientRadius = CGFloat() {
didSet { setNeedsDisplay() }
}
var colors = [CGColor]() {
didSet { setNeedsDisplay() }
}
var locations = [CGFloat]() {
didSet { setNeedsDisplay() }
}
override init(){
super.init()
needsDisplayOnBoundsChange = true
}
required init(coder aDecoder: NSCoder) {
super.init()
}
override init(layer: AnyObject) {
super.init(layer: layer)
}
override class func needsDisplayForKey(key: String) -> Bool {
if key == RadialGradientLayerProperties.gradientOrigin.rawValue || key == RadialGradientLayerProperties.gradientRadius.rawValue || key == RadialGradientLayerProperties.colors.rawValue || key == RadialGradientLayerProperties.locations.rawValue {
print("called \(key)")
return true
}
return super.needsDisplayForKey(key)
}
override func actionForKey(event: String) -> CAAction? {
if event == RadialGradientLayerProperties.gradientOrigin.rawValue || event == RadialGradientLayerProperties.gradientRadius.rawValue || event == RadialGradientLayerProperties.colors.rawValue || event == RadialGradientLayerProperties.locations.rawValue {
let animation = CABasicAnimation(keyPath: event)
animation.fromValue = self.presentationLayer()?.valueForKey(event)
return animation
}
return super.actionForKey(event)
}
override func drawInContext(ctx: CGContext) {
guard let colorRef = self.colors.first else { return }
let numberOfComponents = CGColorGetNumberOfComponents(colorRef)
let colorSpace = CGColorGetColorSpace(colorRef)
let deepGradientComponents: [[CGFloat]] = (self.colors.map {
let colorComponents = CGColorGetComponents($0)
let buffer = UnsafeBufferPointer(start: colorComponents, count: numberOfComponents)
return Array(buffer) as [CGFloat]
})
let flattenedGradientComponents = deepGradientComponents.flatMap({ $0 })
let gradient = CGGradientCreateWithColorComponents(colorSpace, flattenedGradientComponents, self.locations, self.locations.count)
CGContextDrawRadialGradient(ctx, gradient, self.gradientOrigin, 0, self.gradientOrigin, self.gradientRadius, .DrawsAfterEndLocation)
}
}
ドキュメントから:「このイニシャライザは、例えば、プレゼンテーション層方式のため、レイヤーのシャドウコピーを作成するために使用されている他の状況でこの方法を使用すると、未定義の振る舞いを生み出すために。たとえば、このメソッドを使用して既存のレイヤーのコンテンツで新しいレイヤーを初期化しないでください。カスタムレイヤーサブクラスを実装する場合、このメソッドをオーバーライドしてインスタンス変数の値を新しいオブジェクトにコピーできます。スーパークラスの実装を呼び出す。 – matt