首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >创建具有自定义形状孔的图层蒙版

创建具有自定义形状孔的图层蒙版
EN

Stack Overflow用户
提问于 2011-04-20 02:52:32
回答 1查看 12.5K关注 0票数 16

我花了太多时间试图弄清楚这一点,但就是找不到一个可行的解决方案。

情景: 1.手机上显示“某物”的图片。2.在图像的顶部放置半透明(例如蓝色)层,完全覆盖图像。3.在这一层中存在一个“洞”,该层的那一部分是完全透明的,并且是可移动的。

一个例子可以是缩放效果,你可以在图像周围移动这个“洞”。在洞内,你可以正常地看到图像,而在洞外,它被半透明层覆盖。注意:我是在cocos2d层中实现这一点的,在该层中,图像由CCSprite表示。不过,如果没有使用cocos,这应该无关紧要。

问题:我曾尝试使用CAShapeLayer和位图作为掩码,但都不起作用(参见下面的代码片段)。使用CAShapeLayer,我为‘孔’创建了一个UIBezierPath,并将其应用于彩色图层。但是,只有孔显示颜色,而其余部分是透明的。对于图像,蒙版根本不起作用(我不知道为什么)。我甚至试过蒙面口罩,看看能不能用。我还尝试了交换颜色around...from白色和黑色,以清晰的填充和背景。

一个简单的解决方案,如果存在的话,将是反转UIBezierPath的区域。我也尝试过使用path...but进行剪辑,但没有成功。

我希望它是一些简单的-愚蠢的东西,我只是忽略了它。也许你们中的一个会看到这一点。我还不关心的动人的部分。我需要先让实际的面具工作起来。示例代码忽略了iPhone SDK和openGL之间的y轴差异。

CAShapeLayer示例:

CGSize winSize = [[CCDirector sharedDirector] winSize];
UIImage* img = [UIImage imageNamed:@"zebra.png"];
CCSprite* spr = [CCSprite spriteWithCGImage:img.CGImage key:@"img"];
spr.position = ccp( winSize.width / 2, winSize.width / 2 );
[self addSprite:spr];

UIBezierPath* path = [UIBezierPath bezierPathWithRect:rectHole];
CAShapeLayer* maskLayer = [CAShapeLayer layer];
maskLayer.bounds = [spr boundingBox];
maskLayer.position = spr.position;
maskLayer.fillColor = [UIColor whiteColor].CGColor;
maskLayer.backgroundColor = [UIColor clearColor].CGColor;
maskLayer.path = path.CGPath;

CALayer* colorLayer = [CALayer layer];
colorLayer.bounds = [spr boundingBox];
colorLayer.position = maskLayer.position;
[colorLayer setMask:maskLayer];

[[[[CCDirector sharedDirector] openGLView] layer] addSublayer:colorLayer];

多层蒙版示例:

CGSize winSize = [[CCDirector sharedDirector] winSize];
UIImage* img = [UIImage imageNamed:@"zebra.png"];
CCSprite* spr = [CCSprite spriteWithCGImage:img.CGImage key:@"img"];
spr.position = ccp( winSize.width / 2, winSize.width / 2 );
[self addSprite:spr];

UIBezierPath* path = [UIBezierPath bezierPathWithRect:rectHole];
CAShapeLayer* maskLayer = [CAShapeLayer layer];
maskLayer.bounds = [spr boundingBox];
maskLayer.position = spr.position;
maskLayer.fillColor = [UIColor whiteColor].CGColor;
maskLayer.backgroundColor = [UIColor clearColor].CGColor;
maskLayer.path = path.CGPath;

UIBezierPath* pathOuter = [UIBezierPath bezierPathWithRect:img.frame];
CAShapeLayer* outerLayer = [CAShapeLayer layer];
outerLayer.bounds = [spr boundingBox];
outerLayer.position = spr.position;
outerLayer.fillColor = [UIColor blackColor].CGColor;
outerLayer.backgroundColor = [UIColor whiteColor].CGColor;
outerLayer = pathOuter.CGPath;
[outerLayer setMask:maskLayer];

CALayer* colorLayer = [CALayer layer];
colorLayer.bounds = [spr boundingBox];
colorLayer.position = outerLayer.position;
[colorLayer setMask:outerLayer];

[[[[CCDirector sharedDirector] openGLView] layer] addSublayer:colorLayer];

图像蒙版示例:

CGSize winSize = [[CCDirector sharedDirector] winSize];
UIImage* img = [UIImage imageNamed:@"zebra.png"];
CCSprite* spr = [CCSprite spriteWithCGImage:img.CGImage key:@"img"];
spr.position = ccp( winSize.width / 2, winSize.width / 2 );
[self addSprite:spr];

CGRect r = [spr boundingBox];
CGSize sz = CGSizeMake( r.size.width, r.size.height );
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
CGContextRef context = CGBitmapContextCreate( NULL, w, h, 8, 0, colorSpace, kCGBitmapByteOrderDefault | kCGImageAlphaNone );
CGColorSpaceRelease( colorSpace );
CGContextSetFillColorWithColor( context, [UIColor whiteColor].CGColor );
CGContextFillRect( context, r );
CGContextSetFillColorWithColor( context, [UIColor blackColor].CGColor );
CGContextFillRect( context, rectHole );
CGImageRef ref = CGBitmapContextCreateImage( context );
CGContextRelease( context );

CALayer* maskLayer = [CALayer layer];
maskLayer.bounds = [spr boundingBox];
maskLayer.position = spr.position;
[maskLayer setContents:(id)ref];

CALayer* colorLayer = [CALayer layer];
colorLayer.bounds = [spr boundingBox];
colorLayer.position = maskLayer.position;
[colorLayer setMask:maskLayer];

[[[[CCDirector sharedDirector] openGLView] layer] addSublayer:colorLayer];
CGImageRelease( ref );
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-05-12 04:15:57

在学习了其他核心图形技术后,我又回到了这一点。该解决方案最接近上面的多层蒙版示例。但是,您需要将两条路径以相反的方向组合成一个UIBezierPath,而不是创建一个内层和外层。

因此,例如创建要裁剪的内部区域的路径(CW)。注: x,y,w,h指的是“孔”的原点和大小。

      [path moveToPoint:ccp(x,y)];
      [path addLineToPoint:ccp(x+w,y)];
      [path addLineToPoint:ccp(x+w,y+h)];
      [path addLineToPoint:ccp(x,y+h)];
      [path addLineToPoint:ccp(x,y)];

然后,将相反方向的外部区域(CCW)添加到同一路径。注意: x,y,w,h指的是外矩形的原点和大小。

      [path moveToPoint:ccp(x,y)];
      [path addLineToPoint:ccp(x,y+h)];
      [path addLineToPoint:ccp(x+w,y+h)];
      [path addLineToPoint:ccp(x+w,y)];
      [path addLineToPoint:ccp(x,y)];

然后将此路径应用于一个层(maskLayer),该层用作最终层(colorLayer)上的蒙版。不需要"outerLayer“。

票数 13
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5721196

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档