Я потратил слишком много времени, пытаясь понять это, и просто не могу найти работоспособного решения.
Ситуация: 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 );