
Rubyでどう書く?:RubyCocoa+Core Animationでお手軽アニメーション
佐藤伸吾(KBMJ)
2008-08-14 08:00:00
問題
RubyCocoaは、Mac OS XのCocoaオブジェクトをRubyスクリプトからRubyオブジェクトとして扱うための、Ruby用ライブラリとフレームワークです。RubyCocoaを用いれば、RubyでCocoaアプリケーションを記述することができるのです。
Core AnimationはMax OS Xのフレームワークで、その利点は手軽さにあります。普通にアニメーションプログラミングを行おうとすると、時間軸管理、非同期な描画スレッド、パフォーマンスの向上など、考慮すべき点があまりにも多すぎます。
しかし、Core Animationを用いれば、面倒な部分はOSに任せて、自分の実現したいことに集中できるのです。
今回はRubyCocoaとMac OS XのフレームワークであるCore Animationを使って、お手軽にアニメーションを作成してみましょう。
回答例
AppController.rbを作成し、以下のように記述します。
require 'osx/cocoa' OSX.require_framework 'QuartzCore' class AppController < OSX::NSObject ib_outlet :window ib_outlet :view ib_action :pressPosition ib_action :pressRotation ib_action :pressSepia ib_action :pressBloom ib_action :pressHole ib_action :pressZoom ib_action :pressHalftone def awakeFromNib bitmapImage = OSX::NSBitmapImageRep.imageRepWithContentsOfFile_('/Users/ssato/Pictures/ruby.png') image = bitmapImage.CGImage() layer = OSX::CALayer.layer() layer.contents = image layer.frame = OSX::CGRectMake(0,0,995/4,996/4) black=OSX::CGColorCreateGenericRGB(0,0, 0,1.0) backgroundLayer=OSX::CALayer.layer() backgroundLayer.backgroundColor=black backgroundLayer.addSublayer_(layer) @view.setLayer_(backgroundLayer) @view.setWantsLayer_(true) end def pressPosition(sender) animation = OSX::CABasicAnimation.animationWithKeyPath_('position') animation.duration = 1.0 layer = @view.layer.sublayers.objectAtIndex_(0) position = layer.position animation.fromValue = OSX::NSValue.valueWithPoint_(OSX::NSPointFromCGPoint(position)) position.x += 256; position.y += 160; animation.toValue = OSX::NSValue.valueWithPoint_(OSX::NSPointFromCGPoint(position)) animation.autoreverses = true animation.repeatCount = 4 layer.addAnimation_forKey_(animation, 'positionAnimation') end def pressRotation(sender) animation = OSX::CABasicAnimation.animationWithKeyPath_('transform') animation.duration = 0.5 animation.autoreverses = true animation.repeatCount = 4 transform = OSX::CATransform3DIdentity animation.fromValue = OSX::NSValue.valueWithCATransform3D(transform) transform = OSX::CATransform3DMakeRotation(Math::PI, 0, 1.0, 0) transform.m34 = 1.0 / -420.0 animation.toValue = OSX::NSValue.valueWithCATransform3D(transform) layer = @view.layer.sublayers.objectAtIndex_(0) layer.addAnimation_forKey_(animation, 'transformAnimation') end def pressSepia(sender) filter = OSX::CIFilter.filterWithName_('CISepiaTone') filter.setDefaults() layer = @view.layer.sublayers.objectAtIndex_(0) layer.name = 'sepiaFilter' layer.setFilters_(OSX::NSArray.arrayWithObject_(filter)) end def pressBloom(sender) filter2 = OSX::CIFilter.filterWithName_('CIBloom') filter2.setDefaults filter2.setValue_forKey_(OSX::NSNumber.numberWithFloat_(0.0), 'inputIntensity') filter2.setValue_forKey_(OSX::NSNumber.numberWithFloat_(5.0), 'inputRadius') filter2.setName_('bloomFilter') layer = @view.layer.sublayers.objectAtIndex_(0) layer.setFilters_(OSX::NSArray.arrayWithObject_(filter2)) pluseAnimation = OSX::CABasicAnimation.animation pluseAnimation.keyPath = 'filters.bloomFilter.inputIntensity' pluseAnimation.fromValue = OSX::NSNumber.numberWithFloat_(0.0) pluseAnimation.toValue = OSX::NSNumber.numberWithFloat_(1.5*2) pluseAnimation.duration = 1.0 pluseAnimation.repeatCount = 4 pluseAnimation.autoreverses = true layer.addAnimation_forKey_(pluseAnimation, 'bloom') end def pressHole(sender) filter = OSX::CIFilter.filterWithName_('CIHoleDistortion') filter.setDefaults() layer = @view.layer.sublayers.objectAtIndex_(0) layer.setFilters_(OSX::NSArray.arrayWithObject_(filter)) end def pressZoom(sender) filter = OSX::CIFilter.filterWithName_('CIZoomBlur') filter.setDefaults() layer = @view.layer.sublayers.objectAtIndex_(0) layer.setFilters_(OSX::NSArray.arrayWithObject_(filter)) end def pressHalftone(sender) filter = OSX::CIFilter.filterWithName_('CICMYKHalftone') filter.setDefaults() layer = @view.layer.sublayers.objectAtIndex_(0) layer.setFilters_(OSX::NSArray.arrayWithObject_(filter)) end end
Interface Builderで画像1のようにコンポーネントを配置します。

NSObjectを追加して、ClassにAppcontrollerを指定します(画像2)。

OutletsとActionsのConnectionを画像3のように設定します。

実行結果
Positionボタンを押すと、画像が斜めに移動します(画像4)。

Rotationボタンを押すと画像が回転し、Sepiaをクリックすると画像がセピア色になります(画像5)。

同様に、Bloomは画像が光り輝き(画像6)、Holeは画像に穴が空きます(画像7)。Zoomボタンはズームエフェクト(画像8)で、Halftoneはハーフトーンフィルタです(画像9)。




解説
folllow builer on
twitter
- 新着記事
- 特集
- ブログ
- 企画特集
-
ゼロトラストに不可欠なID管理
-
Kubernetesの認定制度が開始
-
講演の見どころを紹介
-
漫画で解説!運用管理のコツ
-
モバイルデバイスもターゲットに!
-
いままさに社会にとっての転換点
-
話題のセキュリティ事故体験ゲーム
-
DXができない企業が滅びる理由
-
内部不正や不注意をどう防ぐ?
-
現場主導の業務変革のポイント
-
連載!プロが語るストレージ戦略
-
デジタルを当たり前と言えるか?
-
明日からではもう遅い?!
-
幸せ?不幸?ひとり情シス座談会
-
ビッグデータ最前線!
-
さあ、クラウドで解決しよう。
-
特集:IT最適化への道
-
利便性とセキュリティの両立
-
常識を疑え!
-
次の一手はこれだ!
-
企業DXのキモはクラウドにあり
-
連載!プロが語るストレージ戦略
-
中小企業でのひとり情シスIT運用術
-
セキュリティの今を知る
-
連載!プロが語るストレージ戦略