我对 iOS 还是很陌生,虽然我不知道为什么这不起作用。
我有 2 个单独的 UIImageView
- 的背景'。这是一张将应用图层蒙版的图片,因此您只能看到图像的一部分。
- “蒙版图像”是它自己的独立图像,可以旋转、平移、捏缩放。旋转/缩放的代码工作正常,是标准代码。
我要做的是创建一个与“蒙版图像”的当前位置/旋转/比例相匹配的 CGPath
这是我的代码,用于获取“蒙版图像”的位置并创建一个 CGPAth 以用作图层蒙版。
如果你去 Xcode 并创建一个新的“单视图应用程序”项目,这里是 ViewController 的完整复制粘贴
视图控制器.h:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController <UIGestureRecognizerDelegate>
{
UIImageView *makskedImageView;
UIImageView *maskImageView;
}
@end
视图控制器.m
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UIImage *sourceImage = [UIImage imageNamed:@"forest.jpg"];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, (sourceImage.size.width/2), (sourceImage.size.height/2))];
imageView.image = sourceImage;
[self.view addSubview:imageView];
makskedImageView = imageView;
// Movable Mask
UIImage *frameBorder = [UIImage imageNamed:@"semiTransSquare.png"];
maskImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, (frameBorder.size.width/2), (frameBorder.size.height/2))];
maskImageView.image = frameBorder;
UIPanGestureRecognizer *panGesture2 = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePan:)];
[panGesture2 setDelegate:self];
[maskImageView addGestureRecognizer:panGesture2];
UIPinchGestureRecognizer *pinchGesture2 = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handlePinch:)];
[pinchGesture2 setDelegate:self];
[maskImageView addGestureRecognizer:pinchGesture2];
UIRotationGestureRecognizer *rotateGesture2 = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(handleRotate:)];
[rotateGesture2 setDelegate:self];
[maskImageView addGestureRecognizer:rotateGesture2];
UITapGestureRecognizer *tapGR =[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleTap:)];
[tapGR setDelegate:self];
[tapGR setNumberOfTapsRequired:1];
[maskImageView addGestureRecognizer:tapGR];
[maskImageView setUserInteractionEnabled:YES];
// Add to view to make visible;
[self.view addSubview:maskImageView];
// apply layer mask to makskedImageView
[self grabTransform:maskImageView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)grabTransform:(UIView *)currentView
{
// build the transform you want
CGAffineTransform t = CGAffineTransformIdentity;
CGFloat angle = [(NSNumber *)[currentView valueForKeyPath:@"layer.transform.rotation.z"] floatValue];
CGFloat scale = [(NSNumber *)[currentView valueForKeyPath:@"layer.transform.scale"] floatValue];
t = CGAffineTransformConcat(t, CGAffineTransformMakeScale(scale, scale));
t = CGAffineTransformConcat(t, CGAffineTransformMakeRotation(angle));
NSLog(@"angle: %f, scale: %f", angle, scale);
// Create a mask layer
// Create a mask layer and the frame to determine what will be visible in the view.
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
// CGRect maskRect = currentView.bounds;
// Frame works a lot better.
CGRect maskRect = currentView.frame;
maskRect.origin.x = currentView.frame.origin.x;
maskRect.origin.y = currentView.frame.origin.y;
// Make a Path friendly transform.
CGPoint center = CGPointMake(CGRectGetMidX(currentView.frame), CGRectGetMidY(currentView.frame));
CGAffineTransform transform = CGAffineTransformIdentity;
transform = CGAffineTransformTranslate(transform, center.x, center.y);
transform = CGAffineTransformScale(transform, scale, scale);
transform = CGAffineTransformRotate(transform, angle);
transform = CGAffineTransformTranslate(transform, -center.x, -center.y);
// Create a path and from the rectangle in it.
CGPathRef path = CGPathCreateWithRect(maskRect, &transform);
// Set the path to the mask layer.
[maskLayer setPath:path];
// Release the path since it's not covered by ARC.
CGPathRelease(path);
// Set the mask of the view.
makskedImageView.layer.mask = maskLayer;
}
#pragma mark - Gestures
-(void)handlePan:(UIPanGestureRecognizer *)recognizer
{
CGPoint translation = [recognizer translationInView:self.view];
recognizer.view.center = CGPointMake(recognizer.view.center.x + translation.x,
recognizer.view.center.y + translation.y);
[recognizer setTranslation:CGPointMake(0, 0) inView:self.view];
[self grabTransform:[recognizer view]];
}
-(void)handlePinch:(UIPinchGestureRecognizer *)recognizer
{
recognizer.view.transform = CGAffineTransformScale(recognizer.view.transform, recognizer.scale, recognizer.scale);
recognizer.scale = 1;
[self grabTransform:[recognizer view]];
}
-(void)handleRotate:(UIRotationGestureRecognizer *)recognizer
{
recognizer.view.transform = CGAffineTransformRotate(recognizer.view.transform, recognizer.rotation);
recognizer.rotation = 0;
valueForKeyPath:@"layer.transform.rotation"] floatValue];
[self grabTransform:[recognizer view]];
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
- (void)handleTap:(UIGestureRecognizer *)recognizer
{
[self grabTransform:[recognizer view]];
}
@end
加 2 张图片:Forest.jpg和semiTransSquare.png
现在,当它运行时,它适用于平移,直到我缩放。旋转图像。(由于其他一些代码,现在轮换工作)。
据我所知,比例与中心一起作为它增长/收缩的点,路径似乎从根 x,y 坐标向外扩展。
这可能是设计使然(根据文档 CGPathCreateWithRect),但我看不到将转换应用于 CGPath 并让它与 UIImageView 'Mask Image' 出现在同一位置的方法
性能是一个大问题,使用 CIImage 的类似解决方案非常滞后,因此希望在 CGPath 创建图层蒙版的情况下解决这个问题,如果可能的话,或者同样快的东西。
我错过了什么?对仅限 iOS 6 的解决方案感到满意。
更新:我发现从边界更改为框架让我达到了 90% 的目标:
CGRect maskRect = currentView.frame;
路径现在将匹配视图的旋转和位置。剩下的唯一问题是规模是错误的。它与原始大小匹配,但如果你缩小它就会变得太小,或者如果你增长它就会变得太大。看起来比例不是1:1。现在这么近。