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

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (56)

我花了太多时间试图弄清楚这一点,并且根本找不到可行的解决方案。

情况: 1.手机上显示“某物”的图片。2.将半透明(如蓝色)图层放置在图像顶部,完全覆盖图像。3.该层中的“孔”存在于该层的该部分完全透明且可移动的地方。

一个例子可能是一个缩放效果,您可以在图像周围移动这个“洞”。在洞的内部,您可以正常看到图像,而在半透明图层的外面则可以看到图像。注意:我在cocos2d图层中实现了这一点,图像由CCSprite表示。不过,如果没有使用椰子,这应该不重要。

问题: 我尝试使用CAShapeLayer和位图作为掩码,但没有任何工作(请参阅下面的代码片段)。使用CAShapeLayer,我为'洞'创建一个UIBezierPath并将其应用于彩色图层。但是,只有孔显示颜色,其余是透明的。有了图像,面具根本不起作用(我不知道为什么)。我甚至试图掩盖口罩,看看是否会奏效。我也试着围绕......从白色到黑色交换颜色以清除填充和背景。

一个简单的解决方案,如果存在的话,将是颠倒UIBezierPath的区域。我也试过剪裁,使用路径......但没有运气。

我希望这简直是愚蠢的,我只是俯视。也许你们中的一个会看到这个。我还没有关心的移动部分。我需要先让实际的面具工作。示例代码忽略了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 );
提问于
用户回答回答于

创建要裁剪的内部区域的路径(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)上的蒙版。“外层”是不需要的。

所属标签

可能回答问题的人

  • 爸爸

    腾讯 · 客户端安全 (已认证)

    4 粉丝4 提问5 回答
  • 找虫虫

    0 粉丝0 提问5 回答
  • 不吃貓的鱼oo

    5 粉丝466 提问4 回答
  • uncle_light

    5 粉丝518 提问4 回答

扫码关注云+社区

领取腾讯云代金券