我正在创建一个在我的应用程序中移动的聚光灯,就像这样:
在示例应用程序中(如上所示),背景图层为蓝色,我有一层覆盖在其上,使其变暗,除了一个显示正常的圆形外。我让它工作了(您可以在下面的代码中看到它的工作方式)。在我的真实应用程序中,其他CALayer中存在实际内容,而不仅仅是蓝色。
这是我的问题:它不会动画。我使用CGContext绘制创建圆形(它是黑色图层中的空点)。当您单击示例应用程序中的按钮时,我会在不同大小的不同位置绘制圆形。
我希望它平稳地转换和缩放,而不是像现在这样跳动。可能需要使用不同的创建聚光灯效果的方法,或者可能有我不知道的隐式动画-drawLayer:inContext:调用的方法。
很容易创建示例应用程序:
在示例应用程序中(如上所示),背景图层为蓝色,我有一层覆盖在其上,使其变暗,除了一个显示正常的圆形外。我让它工作了(您可以在下面的代码中看到它的工作方式)。在我的真实应用程序中,其他CALayer中存在实际内容,而不仅仅是蓝色。
这是我的问题:它不会动画。我使用CGContext绘制创建圆形(它是黑色图层中的空点)。当您单击示例应用程序中的按钮时,我会在不同大小的不同位置绘制圆形。
我希望它平稳地转换和缩放,而不是像现在这样跳动。可能需要使用不同的创建聚光灯效果的方法,或者可能有我不知道的隐式动画-drawLayer:inContext:调用的方法。
很容易创建示例应用程序:
- 新建Cocoa应用程序(使用ARC)
- 添加Quartz框架
- 将自定义视图和按钮拖放到XIB上
- 将自定义视图链接到新类(SpotlightView),提供下面的代码
- 删除SpotlightView.h,因为我已经包含了它的内容
- 将按钮的输出链接到-moveSpotlight:动作
//
// 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