如何在UIImageview中添加圆形遮罩并在此过程中更改框架和中心?

11

我想为UIImageView添加一个圆形遮罩。这是我正在使用的函数来添加遮罩..

- (void) addMaskToBounds:(CGRect) maskBounds
{
    CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];

    CGPathRef maskPath = CGPathCreateWithEllipseInRect(maskBounds, NULL);
    maskLayer.bounds = maskBounds;
    [maskLayer setPath:maskPath];
    [maskLayer setFillColor:[[UIColor blackColor] CGColor]];
    maskLayer.position = CGPointMake(maskBounds.size.width/2, maskBounds.size.height/2);

    [self.imageView.layer setMask:maskLayer];
}

我可以添加口罩,但问题在于我同时改变了图像帧和中心位置。根据用户的操作,图像会放大或缩小。因此,当图像变小时和变大时,我需要添加两次口罩。由于我正在对框架进行动画处理,而在动画处理时图像变得扭曲或移位。我该如何解决这个问题?

我想最好通过一个示例项目来解释。在这里,我创建了一个演示项目https://github.com/akshaynhegde/MaskImage,请运行它以查看我的问题,并让我知道如何解决这个问题。


这个问题之前已经被问过了:https://dev59.com/aGjWa4cB1Zd3GeqPuMsr - Andreas Ley
2个回答

23

希望这能有所帮助。

    CAShapeLayer *circle = [CAShapeLayer layer];
    // Make a circular shape
    UIBezierPath *circularPath=[UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, _imgView.frame.size.width, _imgView.frame.size.height) cornerRadius:MAX(_imgView.frame.size.width, _imgView.frame.size.height)];

    circle.path = circularPath.CGPath;

    // Configure the apperence of the circle
    circle.fillColor = [UIColor blackColor].CGColor;
    circle.strokeColor = [UIColor blackColor].CGColor;
    circle.lineWidth = 0;

    imgViewToClipCircular.layer.mask=circle;

这并没有解决如何在使用蒙版时对UIImageView进行帧更改动画的初始问题... - Sam
我发现这段代码非常方便,因为我需要为我正在创建的视图创建一个偏心圆形遮罩。首先,我在Interface Builder中使用layer.cornerRadius使视图变成圆形。然后,我使用了这段代码,并在Bezier路径中使用了负Y值来创建它的遮罩。最终的形状看起来很像美式足球,这正是我所需要的。 - Carl Smith

4

好的,既然在我的情况中中心点会改变,使用遮罩是没有帮助的。因此,简单而干净的方法是拥有一个自定义的UiImageView并剪辑绘制路径。

因此,为此,需要子类化UIView并在其中绘制图像并剪辑路径。这里是重写的drawRect函数:

- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextAddEllipseInRect(context, self.bounds);
    CGContextClip(context);
    //The subclass of UIView has a UIImageview as property
    [_image drawInRect:rect];    
}

请注意,您不能直接继承UIImageView类并重写drawRect方法,因为它不会被调用。

UIImageView类已经针对将其图像绘制到屏幕进行了优化。UIImageView不会调用子类的drawRect:方法。如果您的子类需要自定义绘制代码,则建议使用UIView作为基类。


自定义的UIImageView解决方案是我以前使用的,因此这个解决方案对我来说很合适。它看起来更接近iOS 7的样式。 - CVertex
1
你也可以更改遮罩层的中心。 - Mrug
请注意,您的评论并不完全正确 - UIView 的这个子类必须有一个 UIImage 作为属性,而不是 UIImageView - RobP

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接