Mac アプリでボタンの幅をアニメーション化し、同時に背景画像と前景画像を作成したいと考えています。そのために、@kgn の素晴らしいライブラリ BBlock ( https://github.com/kgn/BBlock ) を使用しています。
問題は、背景画像が互いに後ろに描画されているように見えるため、ボタンを縮小すると背景画像のアニメーションさえ見えず、途切れているように見えることです。
幅の変更を「アニメーション化」するこの方法は、setImage を使用するだけで機能しますが、背景画像を使用する利点は得られません。
ボタンを段階的に拡大縮小するカスタム ボタンを作成しました (基本的にはアニメーション化します)。実行ごとにボタンのサイズを 1 ピクセルずつ変更し、画像、背景画像、代替背景画像も 1 ピクセルずつ変更します。
- (void)scaleTestButtonUntilWidth:(int)width{
[NSTimer scheduledTimerRepeats:YES withTimeInterval:timeInterval andBlock:^{
if (self.width == width) {
return;
}
int newSize;
if (width > self.width) {
newSize = self.width += 1;
}else if (width < self.width){
newSize = self.width -= 1;
}
self.width = newSize;
[self setImage:self.image];
[self setAlternateBackgroundImage:[self alternateBGImage]];
[self setBackgroundImage:[self BGImage]];
}];
}
setBackgroundImage は次のようになり、setAlternateBackgroundImage の実装は同じです。
- (void)setBackgroundImage:(NSImage *)backgroundImage{
[self setImage:[self imageWithBackgroundImage:backgroundImage
andIcon:self.image]];
[self setButtonType:NSMomentaryChangeButton];
[self setBordered:NO];
}
実際に画像を描画するメソッドを呼び出します:
- (NSImage *)imageWithBackgroundImage:(NSImage *)background andIcon:(NSImage *)icon{
return [NSImage imageForSize:background.size withDrawingBlock:^{
NSRect bounds = NSZeroRect;
bounds.size = background.size;
NSRect iconRect = NSZeroRect;
iconRect.size = icon.size;
iconRect.origin.x = round(background.size.width*0.5f-iconRect.size.width*0.5f);
iconRect.origin.y = round(background.size.height*0.5f-iconRect.size.height*0.5f);
[background drawInRect:bounds fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
[icon drawInRect:iconRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
}];
}
この方法の助けを借りて:
+ (NSImage *)imageForSize:(NSSize)size withDrawingBlock:(void(^)())drawingBlock{
if(size.width <= 0 || size.width <= 0){
return nil;
}
NSImage *image = [[NSImage alloc] initWithSize:size];
[image lockFocus];
drawingBlock();
[image unlockFocus];
#if !__has_feature(objc_arc)
return [image autorelease];
#else
return image;
#endif
}