分針と時針を加えて時計の完成:iPhoneアプリでアナログ時計を作る



前回、iPhoneアプリのアナログ時計の秒針が、iPhoneのローカル時刻を反映して動くようにしました。あとは、分針と時針を加えて

時計を完成させるだけです。

秒針は、時刻を反映した後、1秒に6度回転する動きをさせれば良かったので私でも考えることができました。しかし、分針と時針は少し頭を使いそうです。自分の脳を鍛えるために考えても良かったのですが、ここは時間節約ということでググりました。
コチラのページ(「YoheiM.NET」)にHTML5でアナログ時計を作成ソースコードが公開されていたので、ここから針を回転させるロジックだけ頂きました。
ソースコードは、以下のようになりました。

@implementation acViewController

CALayer *sec_hand;
CALayer *min_hand;
CALayer *hour_hand;
NSTimer *timer;

- (void) onTimer:(CFRunLoopTimerRef *)timer {
    [self setClock];
}

- (void)setClock {
    NSDate *now =[NSDate date];
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    
    [formatter setDateFormat:@"kk"];
    int now_h = [[formatter stringFromDate:now] intValue];
    [formatter setDateFormat:@"mm"];
    int now_m = [[formatter stringFromDate:now] intValue];
    [formatter setDateFormat:@"ss"];
    int now_s = [[formatter stringFromDate:now] intValue];
    
    //秒針の動き
    CATransform3D transform_s = CATransform3DIdentity;
    transform_s = CATransform3DRotate(transform_s, (360 * now_s / 60) * M_PI / 180.0, 0, 0, 1);
    sec_hand.transform = transform_s;
    
    //分針の動き
    CATransform3D transform_m = CATransform3DIdentity;
    transform_m = CATransform3DRotate(transform_m, (360 * now_m / 60 + ((360 / 60) * now_s /60)) * M_PI / 180.0, 0, 0, 1);
    min_hand.transform = transform_m;
    
    //時針の動き
    CATransform3D transform_h = CATransform3DIdentity;
    transform_h = CATransform3DRotate(transform_h, (360 * now_h / 12 + ((360 / 12) * now_m / 60)) *M_PI / 180.0, 0, 0, 1);
    hour_hand.transform = transform_h;    
}

- (void)viewWillAppear:(BOOL)animated{
    self.view.layer.contents =(id)[UIImage imageNamed:@"oboeyo_clock_back.png"].CGImage;
    
    CALayer *baseLayer =[self.view layer];
    
    CALayer *layer_clock_plate =[CALayer layer];
    layer_clock_plate.bounds =CGRectMake(0, 0, 303, 303);
    layer_clock_plate.position =CGPointMake(160, 180);
    layer_clock_plate.contents =(id)[UIImage imageNamed:@"oboeyo_clock_plate.png"].CGImage;
    [baseLayer addSublayer:layer_clock_plate];
    
    
    //分針
    min_hand =[CALayer layer];
    min_hand.bounds =CGRectMake(0, 0, 16, 120);
    min_hand.anchorPoint =CGPointMake(0.5, 0.93);
    min_hand.position =CGPointMake(160, 180);
    min_hand.contents =(id)[UIImage imageNamed:@"min_hand.png"].CGImage;
    [baseLayer addSublayer:min_hand];
    
    //時針
    hour_hand =[CALayer layer];
    hour_hand.bounds =CGRectMake(0, 0, 16, 100);
    hour_hand.anchorPoint =CGPointMake(0.5, 0.92);
    hour_hand.position =CGPointMake(160, 180);
    hour_hand.contents =(id)[UIImage imageNamed:@"hour_hand.png"].CGImage;
    [baseLayer addSublayer:hour_hand];
    
    //秒針
    sec_hand =[CALayer layer];
    sec_hand.bounds =CGRectMake(0, 0, 20, 140);
    sec_hand.anchorPoint =CGPointMake(0.5, 0.93);
    sec_hand.position =CGPointMake(160, 180);
    sec_hand.contents =(id)[UIImage imageNamed:@"sec_hand.png"].CGImage;
    [baseLayer addSublayer:sec_hand];

    
    [self setClock];
    [self startClock];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (void) startClock {
    timer = [NSTimer 
             scheduledTimerWithTimeInterval:0.1
             target: self 
             selector:@selector(onTimer:) 
             userInfo:nil 
             repeats:YES];
}
@end

前回、時計が表示された直後に、針が現在時刻まで回転する動きが見えてしまうというチョットした問題がありました。
そこで、毎秒動きを更新するonTimerの内容をsetClockメソッドとして外に出し、viewWillAppearメソッドで最初に1度針を回転させておくようにしました。以降は、onTimeroメソッドがsetClockメソッドを繰り返し呼び出すようになります。
これで、見た目には最初からローカル時刻が反映された状態で時計を見ることができます。

回転の中心が分かり易くなるよう、針の絵も変えておきました。ちょっと面倒なのは、絵の大きさや中心点を変えてpngを読み込み直す度に、ソースコードも修正しなければならない点です。Flashだったら、ソースコードはいじらずに、ムービークリップの絵を変えて中心点をズラすだけで済みますからね。



いや〜しかし、自分のiPhoneでアナログ時計が動いているところを見ると、やっとオリジナルのアプリ完成が近づいて来た感じがして感動します。そして、今までにないくらいテンション上がってきました。
次は、午前・午後に合わせて背景の絵を変えたいと思います。