在 UIView Mask 中限制 UIPanGestureRecognizer

restrict UIPanGestureRecognizer in UIView Mask

我使用 UIBezierPath 将 UIView(240 * 240) 屏蔽成三角形,如下所示:

path = [UIBezierPath new];
[path moveToPoint:(CGPoint){0, 240}];
[path addLineToPoint:(CGPoint){120,0}];
[path addLineToPoint:(CGPoint){240,240}];
[path addLineToPoint:(CGPoint){0,240}];
[path closePath];

CAShapeLayer *mask = [CAShapeLayer new];
mask.frame = self.viewShape.bounds;
mask.path = path.CGPath;
self.viewShape.layer.mask = mask;

上图三角形区域为遮罩。现在我有了 "Coca-Cola" 的图像,它只能在三角形蒙版中移动。因此,为此我已将 UIPanGestureRecognizer 应用到 UIIMageView 并按以下方式限制其框架。

- (void)handlePanGesture:(UIPanGestureRecognizer *)gestureRecognizer
{
    CGPoint touchLocation = [gestureRecognizer locationInView:self.viewShape];

    CGRect boundsRect;

    BOOL isInside = [path containsPoint:CGPointMake(self.innerView.center.x, self.innerView.center.y)];
    NSLog(@"value:%d",isInside);
    if (isInside) {
        NSLog(@"inside");
        self.innerView.center = touchLocation;
    }else{
        NSLog(@"outside");
    }
}

我上面的 if 条件执行成功但是当控制进入 else 条件时我无法将我的 ImageView 拖回掩码框架内.

所以,我的问题是当调用 else block(outside) 时,我应该能够再次将 imageView 拖到 Mask 的框架内。

我怎样才能做到这一点?

保存对图像视图最后一个中心的引用是实现此目的的一种方法。 在您的自定义视图中;

CGPoint lastValidCenter; //initially it is the center of imageview;

在代码中

NSLog(@"value:%d",isInside);
    if (isInside) {
        NSLog(@"inside");
        self.innerView.center = touchLocation;
        lastValidCenter = self.innerView.center;
    }else{
        NSLog(@"outside");
        self.innerView.center = lastValidCenter;
    }

你的计算有问题。您需要做的是检查 UIImageView 的左上角和右上角是否包含带有 UIBezirePath 实例的点。 之所以如此,是因为当图像移动时,这两个角都会首先尝试出去。所以只需检查一下,你就会得到你想要的输出。

BOOL isInside = [path containsPoint:CGPointMake(CGRectGetMinX(self.innerView.bounds), CGRectGetMinY(self.innerView.bounds))];
isInside = isInside || [path containsPoint:CGPointMake(CGRectGetMaxX(self.innerView.bounds), CGRectGetMinY(self.innerView.bounds))];
if (isInside) {
//Move your UIImageView
}
else {
//Don't move
}

我修改了 Meth 的部分代码。代码如下:

self.innerView.center = touchLocation;
BOOL isInside = [path containsPoint:CGPointMake(self.innerView.center.x, self.innerView.center.y)];
if (isInside) {
        NSLog(@"inside");
        self.innerView.center = touchLocation;
        lastValidCenter = self.innerView.center;
    }else{
        NSLog(@"outside");
        self.innerView.center = lastValidCenter;
    }