创build自定义形状的图层蒙版

我花了太多的时间来解决这个问题,根本找不到一个可行的解决scheme。

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

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

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

一个简单的解决scheme,如果存在的话,将颠倒UIBezierPath的区域。 我也尝试过裁剪,使用path…但没有运气。

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

在学习了其他核心graphics技术之后,我又回到了这里。 该解决scheme最接近上面的多层掩码示例。 但是,不需要创build内层和外层,而需要将两个path合并到一个单向的UIBezierPath中。

所以,例如,创build一个内部区域的path被裁剪(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)的外部区域添加到相同的path中。 注: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)]; 

然后将该path应用于图层(maskLayer),该图层用作最后图层(colorLayer)上的遮罩。 “外层”是不需要的。