前回は履歴の矩形を NSView に直接描画していた。今回はこれを Core Animation に切り替え、各矩形がアニメーションできるようにお膳立てする。
カスタムレイヤー
CALayer をサブクラス化して履歴矩形1つを表すレイヤークラスを用意した。
@interface SelectionHistoryLayer : CATextLayer { } + (SelectionHistoryLayer*)layerWithFrame:(NSRect)frame; @end初期化コード
- (id)initWithFrame:(NSRect)frame { if (self = [super init]) { self.frame = NSRectToCGRect(frame); // TODO: convert coordination CGColorRef colorRef; colorRef= CGColorCreateGenericGray(0.0f, 0.3f); self.backgroundColor = colorRef; CGColorRelease(colorRef); colorRef= CGColorCreateGenericGray(0.0f, 0.5f); self.borderColor = colorRef; CGColorRelease(colorRef); self.cornerRadius = 7.0f; self.layoutManager = [CAConstraintLayoutManager layoutManager]; // text CATextLayer* textLayer = [CATextLayer layer]; colorRef= CGColorCreateGenericGray(1.0f, 1.0f); textLayer.string = [NSString stringWithFormat:@"%d x %d", (int)frame.size.width, (int)frame.size.height]; textLayer.font = @"Lucida-Grande"; textLayer.fontSize = 13.0; textLayer.foregroundColor = colorRef; [self addSublayer:textLayer]; CGColorRelease(colorRef); [textLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidX relativeTo:@"superlayer" attribute:kCAConstraintMidX]]; [textLayer addConstraint:[CAConstraint constraintWithAttribute:kCAConstraintMidY relativeTo:@"superlayer" attribute:kCAConstraintMidY]]; } return self; }背景色を黒の半透明にして角を丸くする。さらに CATextLayer を追加してサイズを表示する。この時 addConstraint を使うと CATextLayer を中心位置にレイアウトすることができる。
表示はこんな感じ。
履歴矩形の表示
カスタムレイヤーを SimpleCap に組み込んで使う。こんな感じ。
- (void)setupSelectionHistoryLayers { CaptureView *view = [_capture_controller view]; // clean up [view.layer removeFromSuperlayer]; // [1] background layer // TODO:multi screen CALayer* backgroundLayer = [CALayer layer]; backgroundLayer.frame = NSRectToCGRect([view frame]); CGColorRef backgroundColorRef = CGColorCreateGenericGray(0.0f, 0.25f); backgroundLayer.backgroundColor = backgroundColorRef; CGColorRelease(backgroundColorRef); view.layer = backgroundLayer; // [2] history selection layers BOOL currentHasExisted = NO; for (NSValue* historyValue in [[SelectionHistory sharedSelectionHistory] array]) { NSRect historyRect = [historyValue rectValue]; SelectionHistoryLayer* layer = [SelectionHistoryLayer layerWithFrame:historyRect]; [backgroundLayer addSublayer:layer]; if (NSEqualRects(_rect, historyRect)) { currentHasExisted = YES; } } // [3] current selection layer if (!currentHasExisted) { SelectionHistoryLayer* currentLayer = [SelectionHistoryLayer layerWithFrame:_rect]; [backgroundLayer addSublayer:currentLayer]; } }背景用に1つ backgroundLayer を用意してそこへカスタムレイヤーを追加する。[3]で現在表示中の範囲選択も表示しておく。履歴とダブらないようなチェックも入れてある。
実行するとこんな感じ。
おーなんかいい感じだ。
CALayer は毎回作り直している。無駄な気もするが軽いクラスとの触れ込みなので今は気にせずこのままいこう。
文字の明滅
フィルタとアニメーションを組み合わせると文字(レイヤー)を明滅させる効果をつけられる。
コードはこんな感じ。
CIFilter *filter = [CIFilter filterWithName:@"CIBloom"]; [filter setDefaults]; [filter setValue:[NSNumber numberWithFloat:5.0] forKey:@"inputRadius"]; [filter setName:@"pulseFilter"]; [textLayer setFilters:[NSArray arrayWithObject:filter]]; CABasicAnimation* pulseAnimation = [CABasicAnimation animation]; pulseAnimation.keyPath = @"filters.pulseFilter.inputIntensity"; pulseAnimation.fromValue = [NSNumber numberWithFloat: 0.0]; pulseAnimation.toValue = [NSNumber numberWithFloat: 2.0]; pulseAnimation.duration = 1.0; pulseAnimation.repeatCount = 1e100f; pulseAnimation.autoreverses = YES; pulseAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]; [textLayer addAnimation:pulseAnimation forKey:@"pulseAnimation"];
実行例(静止画なのでわかりずらいが文字の周りが明滅している)
参考情報
【特集】Leopardのアニメーションを簡単実装! Core Animationを使いこなす (1) アニメーションプログラミングを身に付けるには"とにかく動かせ" | エンタープライズ | マイコミジャーナル
わかりやすくてとても参考になった。
Core Animationプログラミングガイド: レイヤスタイルプロパティ
レイヤに適用できる視覚効果がわかる。
Core Animationプログラミングガイド: サンプル:Core Animation Menuアプリケーション
Core Animation を使ったサンプルアプリ。レイアウトの取り方や、フィルタのかけかたなどが参考になった。文字の明滅はここからコードを拝借した。
- - - -
SimpleCap内ではflippedしているために座標系がCALayerと異なる。この変換が必要。
Responses
Leave a Response