在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. 執行結果,如同綜合了旋轉/平移與縮放的三個功能於一次,不另外截圖

沒有留言:
張貼留言