メインアプリのビュー全体に配置するために、半透明の黒い背景を持つUIView
を作成しました。ここで目指しているのは、そのUIView
のどこかに、半透明の黒い背景が見えないカットアウトの円の形を作成し、円形の領域を除く画像全体に黒いマスクの効果を与えることです(これはその領域のボタンを強調表示します)。
CAShapeLayer
を使用して円形マスクを作成できましたが、これは逆の効果があります(つまり、ビューの残りの部分がクリアで、円の内側が半透明の黒です。私が欲しいのは、外側のすべてです。半透明の黒を維持するための円、次に内部を明確にするために使用したコードは次のとおりです。逆の方法で機能させるにはどうすればよいですか?私のblackMask
は半透明の黒のビューで、私のbuttonCircle
は明確にしておきたいサークル。
どういうわけか、パスを反転する必要がありますか?
CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init];
CGRect maskRect = buttonCircle.frame;
CGPathRef path = CGPathCreateWithEllipseInRect(maskRect, NULL);
maskLayer.path = path;
CGPathRelease(path);
blackMask.layer.mask = maskLayer;
編集:今これを試してみて、これでマスクがまったく表示されない:
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];
だから、これが私がしたことです。次のように、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]]];
これは、楕円形以外の形状を切り抜くことで改善できる可能性がありますが、ここでの目的には問題がなく、後で簡単に調整できます。うまくいけば、これは他の人を助けます!
黒の画像を使用してマスクしている場合
-(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;
}
これが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)
}
}