Я потратил слишком много времени, пытаясь понять это, и просто не могу найти подходящее решение.
Положение:
1. Изображение «что-то» отображается на телефоне.
2. Полупрозрачный (например, синий) слой помещается поверх изображения, полностью покрывая его.
3. «Дыра» в этом слое существует там, где эта часть слоя полностью прозрачна и подвижна.
Примером может служить эффект масштабирования, когда вы перемещаете эту «дыру» вокруг изображения. Внутри отверстия вы можете нормально видеть изображение, а снаружи оно покрыто полупрозрачным слоем. ПРИМЕЧАНИЕ: я реализую это в слое cocos2d, где изображение представлено CCSprite. Это не должно иметь значения, если кокосы не используются.
Проблема:
Я пытался использовать CAShapeLayer и растровые изображения в качестве масок, но ничего не работает (см. Фрагменты кода ниже). С помощью CAShapeLayer я создаю UIBezierPath для «дыры» и применяю его к цветному слою. Тем не менее, только отверстие показывает цвет, а остальное прозрачно. С изображением маска просто не работает (понятия не имею почему). Я даже пробовал маскировать маски, чтобы посмотреть, сработает ли это. Я также попытался поменять цвета вокруг ... с белого на черный, чтобы очистить для заливки и фона.
Простым решением, если бы оно существовало, было бы инвертировать область UIBezierPath. Я тоже попробовал отсечь, используя путь ... но не повезло.
Я надеюсь, что это что-то простое-глупое, что я просто упускаю из виду. Возможно, один из вас увидит это. Подвижная часть меня пока не волнует. Мне нужно, чтобы фактическая маска работала первой. В примере кода игнорируются различия по оси Y между iPhone SDK и openGL.
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 );