Я создаю прожектор, который перемещается по содержимому в моем приложении, например:
В примере приложения (показано выше) фоновый слойсиний, и у меня есть слой поверх него, который затемняет все, кроме круга, который показывает это нормально.У меня это работает (вы можете увидеть, как в коде ниже).В моем реальном приложении есть не только синее, но и другое содержимое CAL, а не только синее.
Вот моя проблема: он не анимируется.Я использую CGContext
рисунок, чтобы создать круг (который является пустым пятном в другом черном слое).Когда вы нажимаете кнопку в моем примере приложения, я рисую круг другого размера в другом месте.
Я бы хотел, чтобы это плавно переводилось и масштабировалось, а не прыгало, как это происходит в настоящее время.Это может потребовать другого метода создания эффекта прожектора, или может быть способ, которым я не знаю, чтобы неявно анимировать вызов -drawLayer:inContext:
.
Образец приложения легко создать:
- Создание нового приложения Какао (с использованием ARC)
- Добавление структуры Quartz
- Перетащите пользовательский вид и кнопку на XIB
- Ссылка на пользовательскийview для нового класса (SpotlightView) с кодом ниже
- Delete
SpotlightView.h
, поскольку я включил его содержимое в SpotlightView.m - Установите для выхода кнопки действие
-moveSpotlight:
Обновление (свойство mask
)
Мне нравится предложение Дэвида Реннквиста в комментариях использовать свойство затемненного слоя mask
, чтобы вырезатьдыра, которую я мог бы затем самостоятельно передвигать.Проблема в том, что по какой-то причине свойство mask
работает противоположно тому, как я ожидаю, что маска будет работать.Когда я указываю круговую маску, все, что появляется, это круг.Я ожидал, что маска будет работать противоположным образом, маскируя область с помощью 0
alpha.
Маскировка кажется правильным способом, но если мне нужно заполнить весь слой и вырезатьиз дыры, тогда я могу сделать это так, как я первоначально написал.Кто-нибудь знает, как инвертировать свойство -[CALayer mask]
, чтобы нарисованная область была вырезана из изображения слоя?
/ Update
Вот код дляSpotlightView
:
//
// SpotlightView.m
//
#import <Quartz/Quartz.h>
@interface SpotlightView : NSView
- (IBAction)moveSpotlight:(id)sender;
@end
@interface SpotlightView ()
@property (strong) CALayer *spotlightLayer;
@property (assign) CGRect highlightRect;
@end
@implementation SpotlightView
@synthesize spotlightLayer;
@synthesize highlightRect;
- (id)initWithFrame:(NSRect)frame {
if ((self = [super initWithFrame:frame])) {
self.wantsLayer = YES;
self.highlightRect = CGRectNull;
self.spotlightLayer = [CALayer layer];
self.spotlightLayer.frame = CGRectInset(self.layer.bounds, -50, -50);
self.spotlightLayer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
self.spotlightLayer.opacity = 0.60;
self.spotlightLayer.delegate = self;
CIFilter *blurFilter = [CIFilter filterWithName:@"CIGaussianBlur"];
[blurFilter setValue:[NSNumber numberWithFloat:5.0]
forKey:@"inputRadius"];
self.spotlightLayer.filters = [NSArray arrayWithObject:blurFilter];
[self.layer addSublayer:self.spotlightLayer];
}
return self;
}
- (void)drawRect:(NSRect)dirtyRect {}
- (void)moveSpotlight:(id)sender {
[self.spotlightLayer setNeedsDisplay];
}
- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
if (layer == self.spotlightLayer) {
CGContextSaveGState(ctx);
CGColorRef blackColor = CGColorCreateGenericGray(0.0, 1.0);
CGContextSetFillColorWithColor(ctx, blackColor);
CGColorRelease(blackColor);
CGContextClearRect(ctx, layer.bounds);
CGContextFillRect(ctx, layer.bounds);
// Causes the toggling
if (CGRectIsNull(self.highlightRect) || self.highlightRect.origin.x != 25) {
self.highlightRect = CGRectMake(25, 25, 100, 100);
} else {
self.highlightRect = CGRectMake(NSMaxX(self.layer.bounds) - 50,
NSMaxY(self.layer.bounds) - 50,
25, 25);
}
CGRect drawnRect = [layer convertRect:self.highlightRect
fromLayer:self.layer];
CGMutablePathRef highlightPath = CGPathCreateMutable();
CGPathAddEllipseInRect(highlightPath, NULL, drawnRect);
CGContextAddPath(ctx, highlightPath);
CGContextSetBlendMode(ctx, kCGBlendModeClear);
CGContextFillPath(ctx);
CGPathRelease(highlightPath);
CGContextRestoreGState(ctx);
}
else {
CGColorRef blueColor = CGColorCreateGenericRGB(0, 0, 1.0, 1.0);
CGContextSetFillColorWithColor(ctx, blueColor);
CGContextFillRect(ctx, layer.bounds);
CGColorRelease(blueColor);
}
}
@end