Маска UIView с вырезанным кругом
Ive создал UIView
с полупрозрачным черным фоном, чтобы сидеть в моем главном приложении. Цель Im здесь - создать форму вырезанного круга где-то в этом UIView
, где не видно полупрозрачный черный фон, дающий эффект черной маски на все изображение, кроме круговой области (это выделите кнопку в этой области).
Мне удалось использовать CAShapeLayer
для создания круговой маски, но это имело противоположный эффект (т.е. остальная часть зрения ясна, а внутри круга - полупрозрачный черный). из круга, чтобы сохранить полупрозрачный черный цвет, а затем внутри, чтобы быть ясным. Вот код, который я использовал, как бы я мог заставить его работать в обратном направлении? Мой blackMask
- это полупрозрачный черный вид и my buttonCircle
- это идентификатор круга, который должен оставаться ясным.
Возможно, мне нужно каким-то образом инвертировать путь?
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGRect maskRect = buttonCircle.frame;
CGPathRef path = CGPathCreateWithEllipseInRect(maskRect, NULL);
maskLayer.path = path;
CGPathRelease(path);
blackMask.layer.mask = maskLayer;
EDIT: попробуйте это сейчас, не видя никакой маски вообще с этим:
UIView *circularMaskView = [[UIView alloc] initWithFrame:buttonCircle.frame];
circularMaskView.backgroundColor = [UIColor greenColor];
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGPathRef path = CGPathCreateWithEllipseInRect(buttonCircle.frame, NULL);
maskLayer.path = path;
CGPathRelease(path);
circularMaskView.layer.mask = maskLayer;
[blackMask addSubview:circularMaskView];
Ответы
Ответ 1
Итак, вот что я сделал. Я создал собственный подкласс UIView
под названием BlackoutView
, например:
BlackoutView.h
#import <UIKit/UIKit.h>
@interface BlackoutView : UIView
@property (nonatomic, retain) UIColor *fillColor;
@property (nonatomic, retain) NSArray *framesToCutOut;
@end
BlackoutView.m
#import "BlackoutView.h"
@implementation BlackoutView
- (void)drawRect:(CGRect)rect
{
[self.fillColor setFill];
UIRectFill(rect);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(context, kCGBlendModeDestinationOut);
for (NSValue *value in self.framesToCutOut) {
CGRect pathRect = [value CGRectValue];
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:pathRect];
[path fill];
}
CGContextSetBlendMode(context, kCGBlendModeNormal);
}
@end
Затем я создаю его как нормальный и задаю свойства цвету маски, которую я хочу использовать, и кадры, которые нужно вырезать из маски:
[blackMask setFillColor:[UIColor colorWithWhite:0.0f alpha:0.8f]];
[blackMask setFramesToCutOut:@[[NSValue valueWithCGRect:buttonCircleA.frame],
[NSValue valueWithCGRect:buttonCircleB.frame]]];
Это можно было бы улучшить, разрешив мне вырезать другие фигуры, помимо овалов, но это прекрасно для моих целей здесь и будет легко адаптировано для этого позже. Надеюсь, это поможет другим!
Ответ 2
Если вы используете любое черное изображение для маскирования, то
-(void)maskWithImage:(UIImage*)maskImage toImageView:(UIImageView*)imgView{
CALayer *aMaskLayer=[CALayer layer];
aMaskLayer.contents=(id)maskImage.CGImage;
imgView.layer.mask=aMaskLayer;
}
Если у вас есть пользовательский ShapeLayer для маскировки
-(void)maskWithShapeLayer:(CALayer*)layer toImageView:(UIImageView*)imgView{
//Layer should be filled with Black color to mask those part of Image
imgView.layer.mask=layer;
}
Если вы хотите сделать маску ImageView с кругом
-(void)maskWithCircle:(UIImageView*)imgView{
CAShapeLayer *aCircle=[CAShapeLayer layer];
aCircle.path=[UIBezierPath bezierPathWithRoundedRect:imgView.bounds cornerRadius:imgView.frame.size.height/2].CGPath; // Considering the ImageView is square in Shape
aCircle.fillColor=[UIColor blackColor].CGColor;
imgView.layer.mask=aCircle;
}
Ответ 3
Вот мое преобразование принятого ответа в Swift:
public class OverlayView: UIView {
let fillColor: UIColor = UIColor.grayColor()
public var framesToCutOut: Array<NSValue> = [NSValue]()
override public func drawRect(rect: CGRect) {
super.drawRect(rect)
fillColor.setFill()
UIRectFill(rect)
if let context: CGContextRef = UIGraphicsGetCurrentContext() {
CGContextSetBlendMode(context, .DestinationOut)
for value in framesToCutOut {
let pathRect: CGRect = value.CGRectValue()
let path: UIBezierPath = UIBezierPath(ovalInRect: pathRect)
path.fill()
}
CGContextSetBlendMode(context, .Normal)
}
}