標準のCGContextFillEllipseInRect()
コードを使用して、UIView
の-drawRect:
メソッドで円を描いています。ただし、アニメーションで少しパルス(大きくしたり小さくしたり)して、塗りつぶしの強度を変更したいと思います。たとえば、円が赤で塗りつぶされている場合、円をパルスして、パルスアクションに合わせて赤を少し明るくしたり暗くしたりします。 Core Animationの経験があまりないので、これを行う方法について少し迷っています。助けていただければ幸いです。
drawRect:
で円を描かない場合、これははるかに簡単です。代わりに、次のようにCAShapeLayer
を使用するようにビューを設定します。
@implementation PulseView
+ (Class)layerClass {
return [CAShapeLayer class];
}
サイズが変更されるたびに(最初に表示されたときを含む)、システムはlayoutSubviews
をビューに送信します。 layoutSubviews
をオーバーライドして、シェイプを設定し、アニメーション化します。
- (void)layoutSubviews {
[self setLayerProperties];
[self attachAnimations];
}
レイヤーのパス(シェイプを決定する)とシェイプの塗りつぶしの色を設定する方法は次のとおりです。
- (void)setLayerProperties {
CAShapeLayer *layer = (CAShapeLayer *)self.layer;
layer.path = [UIBezierPath bezierPathWithOvalInRect:self.bounds].CGPath;
layer.fillColor = [UIColor colorWithHue:0 saturation:1 brightness:.8 alpha:1].CGColor;
}
レイヤーに2つのアニメーションを添付する必要があります。1つはパス用、もう1つは塗りつぶし色用です。
- (void)attachAnimations {
[self attachPathAnimation];
[self attachColorAnimation];
}
レイヤーのパスをアニメーション化する方法は次のとおりです。
- (void)attachPathAnimation {
CABasicAnimation *animation = [self animationWithKeyPath:@"path"];
animation.toValue = (__bridge id)[UIBezierPath bezierPathWithOvalInRect:CGRectInset(self.bounds, 4, 4)].CGPath;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.layer addAnimation:animation forKey:animation.keyPath];
}
レイヤーの塗りつぶしの色をアニメーション化する方法は次のとおりです。
- (void)attachColorAnimation {
CABasicAnimation *animation = [self animationWithKeyPath:@"fillColor"];
animation.fromValue = (__bridge id)[UIColor colorWithHue:0 saturation:.9 brightness:.9 alpha:1].CGColor;
[self.layer addAnimation:animation forKey:animation.keyPath];
}
両方のattach*Animation
メソッドは、基本的なアニメーションを作成し、自動反転と1秒間の継続時間で無期限に繰り返すように設定するヘルパーメソッドを使用します。
- (CABasicAnimation *)animationWithKeyPath:(NSString *)keyPath {
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:keyPath];
animation.autoreverses = YES;
animation.repeatCount = HUGE_VALF;
animation.duration = 1;
return animation;
}