【Xcode6.2 + iOS 8.4(iPhone5) + MacOX10.9.5】
UIBezierPathはベジェ曲線を描画するクラスですが、この描画そのものをアニメーションさせられないかと調べてみました。
まずはUIBezierPathの使い方、この辺が参考になります。
・[iPhone] UIBezierPath 図形の描画 (Objective-C)
・[Swift] UIBezierPathを使って、直線、楕円、矩形などで描画する
・UIBezierPathで曲線を描画してみた | 丸ノ内テックブログ
・UIBezierPathで図形を描画する。: iPhoneソースコードがきたなくて
で、実際に書いてみたのがこちら。
コードはこんな感じ。
・CircleView.h
// // CircleView.h // testUIBezierPath // // Created by c-geru on 2015/10/04. // Copyright (c) 2015年 c-geru. All rights reserved. // #import <UIKit/UIKit.h> @interface CircleView : UIView @end
・CircleView.m
// // CircleView.m // testUIBezierPath // // Created by c-geru on 2015/10/04. // Copyright (c) 2015年 c-geru. All rights reserved. // #import "CircleView.h" @implementation CircleView // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // 円弧 ------------------------------------- UIBezierPath* arc = [UIBezierPath bezierPathWithArcCenter: CGPointMake(self.frame.size.width/2,self.frame.size.height/2) radius:125.0f startAngle:M_PI/2*-1 endAngle:M_PI*2 clockwise:YES]; UIColor *aColor = [UIColor lightGrayColor]; [aColor setStroke]; arc.lineWidth = 10; // 点線のパターンをセット CGFloat dashPattern[2] = { 2.0f, 4.0f }; [arc setLineDash:dashPattern count:2 phase:0]; [arc stroke]; // 円弧 (アニメーション)------------------------------------- UIBezierPath* arc2 = [UIBezierPath bezierPathWithArcCenter: CGPointMake(self.frame.size.width/2,self.frame.size.height/2) radius:125.0f startAngle:M_PI/2*-1 endAngle:M_PI*4/4 clockwise:YES]; UIColor *aColor2 = [UIColor blueColor]; [aColor2 setStroke]; arc2.lineWidth = 10; // 点線のパターンをセット CGFloat dashPattern2[2] = { 2.0f, 4.0f }; [arc2 setLineDash:dashPattern2 count:2 phase:0]; [arc2 stroke]; } @end
で、この青い部分をローディングバー的にアニメーションしたかったわけです。
基本的にアニメーションはCALayerってことはわかったんだけど、アニメーションさせるためのパラメタの渡し方がよくわかりませんでした。
・iPhone – パスに沿ってアニメーションさせる – Qiita
・CALayerを使ってアニメーションしよう – make.appアプリ開発Tips
更に調べてみると、描画要素(fillColor,strokeColor,lineWidth,lineDashPattern)をUIBezierPathでなく、CALayer側に渡してあげればいいみたい。アニメーションで描画するので、考えてみれば当然か。
・iOS Development Tricks: Custom Circular Progress View for iOS
・CAShapeLayer example – Round corners view with dashed line border | Luka Gabric
最終的にアニメーションできたコードがコレ。
・CircleView.h
// // CircleView.h // testUIBezierPath // // Created by c-geru on 2015/10/04. // Copyright (c) 2015年 c-geru. All rights reserved. // #import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> @interface CircleView : UIView @end
・CircleView.m
// // CircleView.m // testUIBezierPath // // Created by c-geru on 2015/10/04. // Copyright (c) 2015年 c-geru. All rights reserved. // #import "CircleView.h" @implementation CircleView // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. - (void)drawRect:(CGRect)rect { // 円弧 ------------------------------------- UIBezierPath* arc = [UIBezierPath bezierPathWithArcCenter: CGPointMake(self.frame.size.width/2,self.frame.size.height/2) radius:125.0f startAngle:M_PI/2*-1 endAngle:M_PI*2 clockwise:YES]; UIColor *aColor = [UIColor lightGrayColor]; [aColor setStroke]; arc.lineWidth = 10; // 点線のパターンをセット CGFloat dashPattern[2] = { 2.0f, 4.0f }; [arc setLineDash:dashPattern count:2 phase:0]; [arc stroke]; // 円弧 (アニメーション)------------------------------------- UIBezierPath* arc2 = [UIBezierPath bezierPathWithArcCenter: CGPointMake(self.frame.size.width/2,self.frame.size.height/2) radius:125.0f startAngle:M_PI/2*-1 endAngle:M_PI*4/4 clockwise:YES]; if (self.pathLayer == nil) { CAShapeLayer *shapeLayer = [CAShapeLayer layer]; shapeLayer.path = [arc2 CGPath]; shapeLayer.fillColor = [UIColor clearColor].CGColor; shapeLayer.strokeColor = [UIColor blueColor].CGColor; shapeLayer.lineWidth = 10; shapeLayer.lineDashPattern = [NSArray arrayWithObjects:[NSNumber numberWithInt:2], [NSNumber numberWithInt:4], nil]; [self.layer addSublayer:shapeLayer]; self.pathLayer = shapeLayer; } CABasicAnimation *pathAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"]; pathAnimation.duration = 3.0; pathAnimation.fromValue = [NSNumber numberWithFloat:0.0]; pathAnimation.toValue = [NSNumber numberWithFloat:1.0]; [self.pathLayer addAnimation:pathAnimation forKey:@"drawCircleAnimation"]; } @end