2012年11月1日 星期四

UIView的Animation(九)

在UIView使用2D座標矩陣運算的Function


CGAffineTransformMake   2D座標運算,但不能將儲存結果,只能將原始資料運算一次的結果顯示出來。


基本數學可參考
http://tw.myblog.yahoo.com/delphi_bnq/article?mid=-2&next=371&l=a&fid=20

http://blog.csdn.net/likendsl/article/details/7595611

Apple的資料
https://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CGAffineTransform/Reference/reference.html


struct CGAffineTransform
{
  CGFloat a, b, c, d;
  CGFloat tx, ty;
};


CGAffineTransform CGAffineTransformMake (CGFloat a,CGFloat b,CGFloat c,CGFloat d,CGFloat tx,CGFloat ty);

为了把二维图形的变化统一在一个坐标系里,引入了齐次坐标的概念,即把一个图形用一个三维矩阵表示,其中第三列总是(0,0,1),用来作为坐标系的标准。所以所有的变化都由前两列完成。
以上参数在矩阵中的表示为:
 |a    b    0|
 |c    d    0|
 |tx   ty   1|
运算原理:原坐标设为(X,Y,1);
                            |a    b    0|
       [X,Y,  1]      |c    d    0|     =     [aX + cY + tx   bX + dY + ty  1] ;
                            |tx    ty  1|

通常,我們需要將一個圖形關於某一特定點(x0,y0)而非原點旋轉。一般情況下,以下
三步可以實現這種操作:首先,變換坐標空間到(-x0,-y0),然後旋轉,最後將坐標空間變換回(x0,y0)。組合變換公式為:
x'= cos(a) × (x – x0) – sin(a) × (y – y0) + x0
y'= sin(a) × (x – x0) + cos(a) × (y – y0) + y0

example
Image1.transform = CGAffineTransformMake(xScale.value*cos(rotationAngle.value*PI/180), sin(rotationAngle.value*PI/180), -sin(rotationAngle.value*PI/180), yScale.value*cos(rotationAngle.value*PI/180), XOffset.value, YOffset.value); 


以下例子改自前一篇
1. 增加一個2D矩陣轉移的Switch

2. 將元件註冊到mainViewController.h
@property (weak, nonatomic) IBOutlet UISwitch *transferSwitch;
@property (weak, nonatomic) IBOutlet UILabel *transferLabel;

3. 增加相關的程式碼到mainViewController.m
...
@synthesize transferLabel, transferSwitch;
...
- (IBAction)transferAction:(id)sender {
   
    UIButton *button = (UIButton *)sender;
    NSInteger tag = button.tag;
   
    CGContextRef context = UIGraphicsGetCurrentContext();
    [UIView beginAnimations:nil context:context];
    [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
    [UIView setAnimationDuration:kDuration];
   
    switch (tag) {
        case 105:
            [UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:self.view cache:YES];
            break;
        case 106:
            [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES];
            break;
        case 107:
            [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:YES];
            break;
        case 108:
            [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:YES];
            break;
        default:
            break;
    }
   
    self.typeID += 1;
    if (self.typeID > 3) {
        self.typeID = 0;
    }
   
    if (twoImageMode.on == YES) {
       NSUInteger image1 = [[self.view subviews] indexOfObject:self.Image1];
       NSUInteger image2 = [[self.view subviews] indexOfObject:self.Image2];
       [self.view exchangeSubviewAtIndex:image1 withSubviewAtIndex:image2];
    }
    else {
       
        [self removeImageView];
   
        if (image1Enable.on == YES) {
       
       
            if (transferSwitch.on == YES) {
               
               Image1.transform = CGAffineTransformMake(xValueSlider.value*cos(rotationSlider.value*PI/180), sin(rotationSlider.value*PI/180), -sin(rotationSlider.value*PI/180), yValueSlider.value*cos(rotationSlider.value*PI/180), XOffsetSlider.value, YOffsetSlider.value);
            }
            else {

               if (unlimitChange.on == YES)
                   Image1.transform = CGAffineTransformScale(Image1.transform, xValueSlider.value
                                                      , yValueSlider.value);
               else
                   Image1.transform = CGAffineTransformMakeScale(xValueSlider.value
                                                          , yValueSlider.value);
           
               if (unlimitChange.on == YES)
                   Image1.transform = CGAffineTransformRotate(Image1.transform, rotationSlider.value*PI/180);
               else
                   Image1.transform = CGAffineTransformMakeRotation(rotationSlider.value*PI/180);
               
               if (unlimitChange.on == YES)
                   Image1.transform = CGAffineTransformTranslate(Image1.transform, XOffsetSlider.value, YOffsetSlider.value);
               else
                   Image1.transform = CGAffineTransformMakeTranslation(XOffsetSlider.value, YOffsetSlider.value);
           
               if (invertSwitch.on == YES)
                   Image1.transform = CGAffineTransformInvert(Image1.transform);
           
            }
           
            Image1.alpha = transparentSlider.value;
           
            [self.view  addSubview:Image1];
            [self.view sendSubviewToBack:Image1];
        }
        else  {
           
            if (transferSwitch.on == YES) {
               
                Image2.transform = CGAffineTransformMake(xValueSlider.value*cos(rotationSlider.value*PI/180), sin(rotationSlider.value*PI/180), -sin(rotationSlider.value*PI/180), yValueSlider.value*cos(rotationSlider.value*PI/180), XOffsetSlider.value, YOffsetSlider.value);
            }
            else {

               if (unlimitChange.on == YES)
                   Image2.transform = CGAffineTransformScale(Image2.transform, xValueSlider.value
                                                          , yValueSlider.value);
               else
                  Image2.transform = CGAffineTransformMakeScale(xValueSlider.value
                                                              , yValueSlider.value);
           
               if (unlimitChange.on == YES)
                   Image2.transform = CGAffineTransformRotate(Image2.transform, rotationSlider.value*PI/180);
               else
                   Image2.transform = CGAffineTransformMakeRotation(rotationSlider.value*PI/180);
           
               if (unlimitChange.on == YES)
                   Image2.transform = CGAffineTransformTranslate(Image2.transform, XOffsetSlider.value, YOffsetSlider.value);
               else
                   Image2.transform = CGAffineTransformMakeTranslation(XOffsetSlider.value, YOffsetSlider.value);
           
               if (invertSwitch.on == YES)
                   Image2.transform = CGAffineTransformInvert(Image2.transform);
           
            }
           
            Image2.alpha = transparentSlider.value;
           
            [self.view  addSubview:Image2];
            [self.view sendSubviewToBack:Image2];
        }
    }
       
       
    [UIView setAnimationDelegate:self];
    // 动画完毕后调用某个方法
    //[UIView setAnimationDidStopSelector:@selector(animationFinished:)];
    [UIView commitAnimations];
   
    if (change == 1)
        change = 2;
    else
        change = 1;
}
...
- (IBAction)enableTransfer:(id)sender {
    if (transferSwitch.on == YES)
        transferLabel.text = @"起動2D矩陣轉移";
    else
        transferLabel.text = @"關閉2D矩陣轉移";
}


4. 執行結果,如同綜合了旋轉/平移與縮放的三個功能於一次,不另外截圖


沒有留言: