スライドショーの簡易アニメーション(3)

2010. 06. 24
●ビューの回転機能

続いてビューの回転機能を付加します。

といってもデバイスの向きを検出してインターフェイスごと回転させるのではなく、トリプルタップによる画像表示ビューのみを右方向に90度回転させる(回転済みの場合は元に戻す)メソッドrotate90を追加するものです。


●トリプルタップ処理の追加

スライドショーのフルスクリーン化(2)』の『UITouchableImageView.mソースファイルの編集』での説明と同様の手順で、UITouchableImageView.mに

・トリプルタップ処理を呼び出すメソッドtripleTapの追加
・タップ回数を判別するtouchesEnabled:withEvent:メソッドへのトリプルタップ処理の追加

を行います。

サンプルコード『iPhoneBG2/SampleCode/60.04.Slide ( アニメ )』のtouchesEnabled:withEvent:メソッドのcase 3のコメントが『// 2 ダブルタップの処理』となっていますが、正しくは『// 3 トリプルタップの処理』です。
(太字が追加した部分)

- (void)singleTap {
    if (tapCount == 1) {    // シングルタップの確認
        // フルスクリーンの開始と解除
        [slide enterOrExitFullScreen];
    }
}

- (void)doubleTap {
    if (tapCount == 2) {    // ダブルタップの確認
        // スライドショーの開始と停止
        [slide startStop:nil];
    }
}

- (void)tripleTap {
    if (tapCount == 3) {    // トリプルタップの確認
        // 回転
        [self rotate90];
    }
}


- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    // タッチ情報の集合から1つを取り出す
    UITouch *touch = [touches anyObject];

    // タップカウントを取得
    tapCount = touch.tapCount;

    switch (tapCount) {
        case 1:    // シングルタップの処理
            [self performSelector:@selector(singleTap) withObject:nil afterDelay:0.4f];
            break;
        case 2:    // ダブルタップの処理
            [self performSelector:@selector(doubleTap) withObject:nil afterDelay:0.4f];
            break;
        case 3: // トリプルタップの処理
            [self performSelector:@selector(tripleTap) withObject:nil afterDelay:0.4f];
            break;
    }
}

446

tripleTapメソッドは、タップカウントが3回の場合にビューの回転を行うrotate90メソッド(後述)を呼び出します。

tripleTapメソッドはUITouchableImageViewクラス内で記述するので、レシーバはslideではなくselfになることに注意してください。

touchesEnabled:withEvent:メソッドのcase 3は、タップカウントが3回の場合にセレクタで上記tripleTapメソッドを呼び出します。


●アフィン変換によるビューの90度回転

- (void)rotate90 {
    // アニメーションの準備
    [UIView setAnimationsEnabled:YES];
    [UIView beginAnimations:@"Rotate" context:nil];

    // 既に回転済みかを確認
    if (CGAffineTransformIsIdentity(self.transform)) {
        CGAffineTransform trans;

        // 90度回転するアフィン変換を生成
        trans = CGAffineTransformMakeRotation(3.14 / 2.0);

        // 既存のアフィン変換を拡大縮小(480dot→320dot)
        trans = CGAffineTransformScale(trans, 320.0 / 480.0, 320.0 /480.0);

        // アフィン変換を変更
        self.transform = trans;
    }
    else {
        self.transform = CGAffineTransformIdentity;
    }
    // アニメーション実行
    [UIView commitAnimations];
}

447

まずsetAnimationsEnabled:メソッドでアニメーションを有効にします。

次にbeginAnimations:context:メソッドで、アニメーションブロックを開始します。

続いてアフィン変換を使って、時計回りに90度回転と横幅に合わせた縮小のON/OFFを行います。

自身のアフィン変換(UITouchableImageViewのアフィン変換であるself.transform)がオリジナルのアフィン変換(無変換)と同じかどうかを判別し、オリジナルなら回転と縮小の変換をし、変換済みの場合はオリジナルに戻します。

オリジナルのアフィン変換かどうかの判別は、CGAffineTransformIsIdentity関数で行います。

回転はCGAffineTransformMakeRotation関数を用い、角度をラジアンで指定します。

ラジアンは 1π = 180度ですから、90度回転する場合『(3.14 / 2.0)』で間違いは無いのですが、他書籍などでは見た目に分かり易くするため『(90.0 * (M_PI / 180.0))』と記述することが多いようです。

一つ引っかかるのは、『CGAffine Transform Reference』のCGAffineTransformMakeRotationの説明で、引数angleの項に

『In iPhone OS, a positive value specifies counterclockwise rotation and a negative value specifies clockwise rotation. 』

iPhone OSでは正の値を指定すると反時計回りに回転し、負の値を指定すると時計回りに回転します。

とあり、実際の動作と逆になっているのが腑に落ちないところです。

それはさておき、縮小はCGAffineTransformScaleで行っているのですが、本書では値が整数で書かれていますがこのままでは挙動がおかしくなります。

(サンプルコードは正しく記述されていますが)CGAffineTransformScaleの拡大縮小の引数は実数(CGFloat型)で渡す必要がありますので注意してください。

回転・縮小済みのアフィン変換だった場合は、CGAffineTransformIdentityでオリジナルのアフィン変換に戻します。

最期にcommitAnimationsメソッドを呼び出して、アニメーションブロックを閉じます。


・CGAffineTransformISIdentity
(CGAffineTransform)

bool CGAffineTransformIsIdentity (
    CGAffineTransform t
);

アフィン変換が適用されていないものかをチェックします。

tが適用されていない場合はtrue、それ以外はfalseを返します。

t:チェックするアフィン変換を指定します。


・transform
(UIViewクラス)

@property(nonatomic) CGAffineTransform transform

区域の中心から相対的に、指定した変換をレシーバに適用します。

変換の原点の値はcenterプロパティか、変更されている場合はレイヤのanchorPointプロパティで得られます。
(取得には、元となるCore Animationレイヤオブジェクトのlayerプロパティを使用します)

デフォルト値はCGAffineTransformIdentityです。

このプロパティを変更して、アニメーションをすることができます。

アニメーションブロックで、開始にはbeginAnimations:context:クラスメソッド、終了にはcommitAnimationsクラスメソッドを使います。

デフォルトでは全てcenter値(変更されている場合はanchorPoint値)です。

警告:このプロパティが恒等変換できなかった場合は、frameプロパティの値が未定義となって無視してください。


・CGAffineTransformMakeRotation
(CGAffineTransform)

CGAffineTransform CGAffineTransformMakeRotation (
    CGFloat angle
);

提供した値で回転させたアフィン変換行列を返します。

この関数はCGAffineTransform構造体を生成し、座標系の回転に使用(必要なら再使用)することができます。

行列は以下のような形式になっています。

448

実際の回転の方向は、ターゲットとなるプラットフォームの座標系に依存し、iPhone OSとMac OS Xでは異なります。

この関数で返されるCGAffineTransformデータ構造体は、最初の二つの列のみに値が含まれるため、三列目は常に (0, 0, 1) です。

これらの方程式の結果は、Quartzが点 (x, y) の回転を適用するのに使用します。

449

回転させたオブジェクトを描画にのみ使う場合は、アフィン変換を構成する必要はありません。

回転させた描画を行う最も直接的な方法は、CGContextRotateCTM関数を呼び出すことです。

angle:この行列で回転させる座標系軸の角度をラジアンで指定します。
iPhone OSでは正の値を指定すると反時計回りに回転し、負の値を指定すると時計回りに回転します。
Mac OS Xでは正の値を指定すると時計回りに回転し、負の値を指定すると反時計回りに回転します。


・CGAffineTransformScale
(CGAffineTransform)

CGAffineTransform CGAffineTransformScale (
    CGAffineTransform t,
    CGFloat sx,
    CGFloat sy
);

現在のアフィン変換をスケーリングしたアフィン変換行列を返します。

この関数は、現在のアフィン変換の値にスケーリングした値を追加した、新しいアフィン変換行列の生成に使用します。

新しいアフィン変換は、座標系の拡大縮小に使用(必要なら再使用)することができます。

t:現在のアフィン変換を指定します。

sx:拡大縮小するアフィン変換のx値を指定します。

sy:拡大縮小するアフィン変換のy値を指定します。


・CGAffineTransformIdentity
(CGAffineTransform)

const CGAffineTransform CGAffineTransformIdentity;

恒等変換。
※ 無変換のアフィン変換

450


●CGAffineTransform

CGAffineTransformデータ構造体は、アフィン変換を使った行列を表します。

アフィン変換は、ある座標系の点を指定して、別の座標系に点をマッピングすることです。

アフィン変換は特別なマッピング方法で、長さや角度を維持した平行移動のことですが、必ずしもそうとは限りません。

アフィン変換は平行移動だけでなく、スケーリング(拡大/縮小)、回転といった操作をサポートしていて一般的によく使われますが、斜めに(平行四辺形のように、相対する二辺が平行を維持した変形)することもできます。

QuartzはCGAffineTransformデータ構造体を使って、アフィン変換の生成、連結、適用をする関数を提供します。

アフィン変換関数の使用法についての情報は『Quartz 2D Programming Guide』を参照してください。

通常はアフィン変換を直接生成する必要はありません。

現在のアフィン変換を修正する関数はCGContext Referenceに表されています。

アフィン変換を再利用する予定が無い場合は、CGContextScaleCTM、CGContextRotateCTM、CGContextTranslateCTM、またはCGContextConcatCTMを使用することができます。



参考文献

CGAffine Transform Reference

UIView Class Reference

基礎からのiOS SDK基礎からのiOS SDK
(2010/10/09)
鶴薗 賢吾、松浦 健一郎 他

商品詳細を見る






Bose QuietComfort 20
0 Comments
Leave a comment
管理者にだけ表示を許可する
Top
0 Trackbacks
Top
Calendar
08 | 2017/09 | 10
Sun Mon Tue Wed Thu Fri Sat
- - - - - 1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Recent Articles
iTunes


Swift
Categories
Tips
Profile

水月杏香

Author:水月杏香
永遠の初心者プログラマ。

Wish List
WACOM


ARC
Technical Q&A
情報プロパティリストキー
Start Developing iOS Apps Today
BOSE

Bose QuietComfort 20
Reference
NSApplicationDelegateプロトコル
NSArrayクラス
NSAutoreleasePoolクラス
NSBundleクラス
NSBundle UIKit追加分
NSCalendarクラス
NSCoderクラス
NSCodingプロトコル
NSCopyingプロトコル
NSDataクラス
NSDateクラス
NSDateFormatterクラス
NSDictionaryクラス
NSEntityDescriptionクラス
NSEnumeratorクラス
NSErrorクラス
NSExceptionクラス
NSFetchRequestクラス
NSFileHandleクラス
NSFileManagerクラス
NSIndexPathクラス
NSIndexPath UIKit追加分
NSKeyedArchiverクラス
NSKeyedUnarchiverクラス
NSKeyValueCodingプロトコル
NSLocaleクラス
NSManagedObjectクラス
NSManagedObjectContextクラス
NSManagedObjectModelクラス
NSMutableArrayクラス
NSMutableCopyingプロトコル
NSMutableDictionaryクラス
NSMutableSetクラス
NSNotificationクラス
NSNotificationCenterクラス
NSNullクラス
NSNumberクラス
NSObjectクラス
NSObject UIKit追加分
NSObjectプロトコル
NSPersistentStoreクラス
NSPersistentStoreCoordinatorクラス
NSPredicateクラス
NSPropertyListSerializationクラス
NSRunLoopクラス
NSSetクラス
NSStringクラス
NSString UIKit追加分
NSTimerクラス
NSTimeZoneクラス
NSURLクラス
NSURLProtectionSpaceクラス
NSURLRequestクラス
NSUserDefaultsクラス
NSValueクラス

UIActionSheetクラス
UIActionSheetDelegateプロトコル
UIActivityIndicatorViewクラス
UIAlertViewクラス
UIAlertViewDelegateプロトコル
UIApplicationクラス
UIApplicationDelegateプロトコル
UIBarButtonItemクラス
UIBarItemクラス
UIButtonクラス
UIColorクラス
UIControlクラス
UIDatePickerクラス
UIDeviceクラス
UIEventクラス
UIFontクラス
UIGestureRecognizerクラス
UIImageクラス
UIImageViewクラス
UIKit Function
UILabelクラス
UINavigationControllerクラス
UINavigationItemクラス
UIPickerViewクラス
UIPickerViewDataSourceプロトコル
UIPickerViewDelegateプロトコル
UIPinchGestureRecognizerクラス
UIResponderクラス
UIScreenクラス
UIScrollViewクラス
UISearchBarクラス
UISearchBarDelegateプロトコル
UISegmentedControlクラス
UISliderクラス
UISwipeGestureRecognizerクラス
UISwitchクラス
UITableViewクラス
UITableViewCellクラス
UITableViewControllerクラス
UITableViewDataSourceプロトコル
UITableViewDelegateプロトコル
UITapGestureRecognizerクラス
UITextFieldクラス
UITextFieldDelegateプロトコル
UITextInputTraitsプロトコル
UITextViewクラス
UITextViewDelegateプロトコル
UIToolbarクラス
UITouchクラス
UIViewクラス
UIViewControllerクラス
UIWebViewクラス
UIWebViewDelegateプロトコル
UIWindowクラス

AVAudioPlayerクラス
AVAudioPlayerDelegateプロトコル

CADisplayLinkクラス
CAEAGLLayerクラス
CALayerクラス

CGAffineTransform
CGBitmapContext
CGColor
CGColorSpace
CGContext
CGGeometry
CGImage
CGPath

EAGLContextクラス
EAGLDrawableプロトコル

Foundation Constants
Foundation Data Types
Foundation Functions

MPMediaItemクラス
MPMediaItemArtworkクラス
MPMediaPlaylistクラス
MPMediaPropertyPredicateクラス
MPMediaQueryクラス
MPMusicPlayerControllerクラス

Randomization Services

System Sound Services
Amazon


OpenGL ES
SQLite
Monthly Archives
Recent Comments
Recent TrackBacks
RSS Link
Visitors
QR Code
QR