I am trying to achieve a transformation like in the image but I only have got a similar transformation but with perspective (which I don't want) using CGATransform3D. How could I achieve this using objective-c? The transformed image should have the same heigh and width than the original but with the base tilted by a given angle.
Thanks in advance for your help.
This is a “shear” or “skew” transformation. Luckily for you, shear transformations are affine transformations, and iOS supports affine transformations at both the UIView
and CALayer
levels. However, it has no convenience functions to construct shear transforms, so let's write one:
static CGAffineTransform affineTransformMakeShear(CGFloat xShear, CGFloat yShear) {
return CGAffineTransformMake(1, yShear, xShear, 1, 0, 0);
}
It's not obvious exactly what xShear
and yShear
mean. xShear
is the tangent of the angle by which the y-axis is skewed, and yShear
is the tangent of the angle by which the x-axis is skewed. This may seem backwards, but it has the visual effect you expect: a non-zero xShear
tilts the figure left or right, and a non-zero yShear
tilts the figure up or down.
Since tan π/4 = 1 (or, if you prefer, tan 45° = 1), the transform returned by affineTransformMakeShear(1, 0)
turns a rectangle into a parallelogram whose left and right edges are at π/4 radians (or 45°).
Demo:
Note that shearing on both axes can be identical to the combination of a rotation and a scale.
Here's my demo code:
#import "ViewController.h"
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIView *shearedView;
@property (strong, nonatomic) IBOutlet UISlider *verticalShearSlider;
@property (strong, nonatomic) IBOutlet UISlider *horizontalShearSlider;
@property (strong, nonatomic) IBOutlet UILabel *verticalShearLabel;
@property (strong, nonatomic) IBOutlet UILabel *horizontalShearLabel;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self updateAppearance:nil];
}
static CGAffineTransform affineTransformMakeShear(CGFloat xShear, CGFloat yShear) {
return CGAffineTransformMake(1, yShear, xShear, 1, 0, 0);
}
- (IBAction)updateAppearance:(id)sender {
CGFloat xShear = self.horizontalShearSlider.value;
CGFloat yShear = self.verticalShearSlider.value;
self.shearedView.transform = affineTransformMakeShear(xShear, yShear);
self.horizontalShearLabel.text = [NSString stringWithFormat:@"%.2f", xShear];
self.verticalShearLabel.text = [NSString stringWithFormat:@"%.2f", yShear];
}
@end