24/7 twenty-four seven

iOS/OS X application programing topics.

MKMapView に CATransform3D を適用するときの注意



@さんがつぶやいてたので気になって調べてみました。

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = 1.0f / -500.0f;
    transform = CATransform3DRotate(transform, 60.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
    
    mapView.layer.transform = transform;
}

こんなふうに書いてみたところ、どうもズーム機能が正常に動作しなくなるようです。
(ズームはするけど拡大率に合わせて再描画してくれない)


で、いろいろ試した結果、どうやら mapView の親ビューのレイヤーに transform を適用した上で、mapView のレイヤーにはその逆行列を適用することで打ち消してあげると正しく動作するようです。
(単純に親ビューのレイヤーに適用するだけではダメ。親ビューのレイヤーに適用した transform は自動的にサブビューのレイヤーにも適用されるので。)
下記がコード例です。

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    CATransform3D transform = CATransform3DIdentity;
    transform.m34 = 1.0f / -500.0f;
    transform = CATransform3DRotate(transform, 60.0f * M_PI / 180.0f, 1.0f, 0.0f, 0.0f);
    
    contentView.layer.transform = transform;
    
    // mapView に逆行列を適用する
    CATransform3D t = CATransform3DInvert(transform);
    mapView.layer.transform = t;
}


実行した結果は下のようになります。ちゃんとズームできてますね。


ちなみに、ズームできなくなるのは行列の m34 要素を変更したときのみで、単に回転やスケールするだけなら問題ないぽいです。


東日本大震災緊急支援募金募集中。国際NGOワールド・ビジョン・ジャパン