前回検証した NSViewAnimation クラスを使って SimpleView にフェードイン/フェードアウト効果を導入する。
パネルウィンドウのクラス SimpleViewerPanel へ show/hideメソッドを用意してこれで制御することにしよう。
SimpleViewerPanel.h
@interface SimpleViewerPanel : NSPanel {
}
- (void)show;
- (void)hide;
@end
以下、実装コード。
SimpleViewerPanel.m
#define FADE_DURATION 0.25
- (void)show
{
if (![self isVisible]) {
[self setAlphaValue:0.0];
[self orderFront:self];
}
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject:self forKey:NSViewAnimationTargetKey];
[dict setObject:NSViewAnimationFadeInEffect forKey:NSViewAnimationEffectKey];
[dict setObject:[NSValue valueWithRect:[self frame]] forKey:NSViewAnimationStartFrameKey];
[dict setObject:[NSValue valueWithRect:[self frame]] forKey:NSViewAnimationEndFrameKey];
NSViewAnimation *anim = [[NSViewAnimation alloc]
initWithViewAnimations:[NSArray arrayWithObject:dict]];
[anim setDuration:FADE_DURATION];
[anim setAnimationCurve:NSAnimationEaseIn];
[anim startAnimation];
[anim release];
}
- (void)hide
{
if (![self isVisible] || [self alphaValue]==0) {
return;
}
NSMutableDictionary* dict = [NSMutableDictionary dictionary];
[dict setObject:self forKey:NSViewAnimationTargetKey];
[dict setObject:NSViewAnimationFadeOutEffect forKey:NSViewAnimationEffectKey];
NSViewAnimation *anim = [[NSViewAnimation alloc]
initWithViewAnimations:[NSArray arrayWithObject:dict]];
[anim setDuration:FADE_DURATION];
[anim setAnimationCurve:NSAnimationEaseIn];
[anim startAnimation];
[anim release];
}
組み込んでみて次のことがわかった。
(1)フェードアウトは不透明度(alpha値)が 0になり、見えなくなるだけ。
NSWindow#isVisible: YES
NSWindow#alphaValue: 1.0=>0.0
(2)フェードインは不透明度を0.0から1.0に変えるだけ。
NSWindow#isVisible: YES
NSWindow#alphaValue: 0.0=>1.0
つまりいずれも不透明度を変えるだけで、ウィンドウそのものを表示したり(#orderFront:)、非表示にしたり(#orderOut:)しているわけではない。アニメーションを行うだけのクラスなので当然の動作といえばそうなのだが、気がつくまでちょと混乱してしまった。
さて上記メソッドを呼ぶ様にした。こんな感じ。
やっぱり、フェードイン/フェードアウトがあると柔らかい感じがしていい。
なお、左上の×でウィンドウを閉じた時にもフェードアウトがかかるよう、NSWindow#close: メソッドをオーバーライドしてある。
- (void)close
{
[self hide];
}
- - - -
こんな便利なクラス(NSViewAnimation)があるとは知らなかった。もっと早く気がつけば吹き出しウィンドウのフェードアウトは簡単にできたのに。。