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