Ruby Freaks Lounge

第18回Ruby on Railsで開発するSilverlightアプリケーション

前回のおさらい

前回記事はSilverlight、IronRubyの基本的な概念の説明と開発環境の紹介、動作確認までを行いました。今回は前回記事の最後で作成したHello Silverlightアプリケーションに簡単な修正を行い、基本的な機能を紹介していきます。

箇条書きで簡単にセットアップの手順をおさらいします。

  1. Ruby/Rails環境を準備(要rubyzipモジュール)
  2. SilverStarプラグインをインストール
  3. ./script/generate silverlight [name]を実行
  4. viewにインターフェイス要素を記述(拡張子xaml)
  5. controllerでrender_silverlightを行う
  6. app/silverlight/xxxx.rbにrubyでマネージコード(制御コード)を記述
  7. http://[host]/[path].xapにアクセスしてみる

準備

前回示したサンプルではrubyのマネージコードにバグがあっても真っ白になるだけです。この後の内容を読者の方に試していただくにあたって、デバッグの必要があります。Silverlightの呼び出し元になるHTMLを以下のように変更してください。

<div id='errorLocation'></div>
<object data="data:application/x-silverlight," type="application/x-silverlight-2" width="600px" height="400px">
  <param name="initParams" value="debug=true, reportErrors=errorLocation" />
  <param name="source" value="/silverlight/test/1.xap"/>
</object>

これで、もしrubyのマネージコードやXAMLの文法エラーがあった場合、errorLocationで示されたHTML要素にエラーメッセージが表示されます。

Silverlightアプリを作ってみる

この節ではSilverlightアプリの開発における基本的な要素について解説を行い、より詳しく知りたい方のためにリファレンスへのリンクを紹介します。

インターフェイス要素へのアクセス

Silverlightのインターフェイス要素には領域(Canvas⁠⁠、矩形(Rectangle⁠⁠、楕円(Elipse⁠⁠、画像(Image)などさまざまな要素があります。

まずは最も基本的な以下の処理を行います。

  1. UI要素に名前をつける
  2. 1.でつけた名前を使ってUI要素を呼び出す
  3. UI要素の属性を変更する

UI要素に名前をつけるには、x:Nameという属性を設定する必要があります。

<Canvas
    x:Class="System.Windows.Controls.Canvas"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="600" Height="460"
    Background="White"
    x:Name="root">
  <TextBlock x:Name="hello" Text="Hello! Silverlight!!" FontSize="64" />
</Canvas>

そして、マネージコードを以下のように変更します。

require "lib/silverlight"
require "mscorlib"

class App < SilverlightApplication
  use_xaml(:type => Canvas, :name => "app")

  def initialize
    hello.text = "Hello! IronRuby!!"
  end
end

$app = App.new

これで最初に表示される文字が「Hello! IronRuby!!」に変わります。

図1 
図1 

要素名をそのままメソッドにしてアクセスすることが可能です(これはプラグインの動作です⁠⁠。hello.text="..."はhelloという名前が設定された要素のtext属性を置き換えています。Silverlight+IronRubyの環境ではhello.textはhello.Textとしても同じです。また、属性の指定ではobject.method_nameとobject.MethodNameは等価です。この記事ではobject.method_nameの形式を使います[1]⁠。

require "lib/silverlight"
require "mscorlib"

class App < SilverlightApplication
  use_xaml(:type => Canvas, :name => "app")

  def initialize
    name = "he" + "llo"
    _(name).text = "Hello! IronRuby!!"
  end
end

$app = App.new

上記は変数名を名前としてアクセスしています。これは最初の例と同じ挙動になります。

Silverlightで頻繁に使われる要素とリファレンスへのリンクをここで紹介します。リファレンスにあるサンプルコードはVB及びC#のものしかありません。しかし、ライブラリは共通ですので、クラス名、プロパティ名、メソッド名は同じものが使えます。適宜読み替えて活用してください。

イベントハンドラ

クリック、ドラッグ&ドロップ、キーボードなどのユーザ入力を処理するためには イベントハンドラを利用します。イベントハンドラはマネージコードのどこでも設定することができます。

require "lib/silverlight"
require "mscorlib"

class App < SilverlightApplication
  use_xaml(:type => Canvas, :name => "app")

  def initialize
    hello.mouse_left_button_down do |s, e|
      s.text = "Click! Silverlight!"
    end

    root.key_down do |s, e|
      hello.text = "Key pushed!" if e.Key = Input::Key.enter
    end
  end
end

$app = App.new

上記の太字部分がハンドラの記述です。これを実行すると、クリックと[enter]キーの入力で文字が変化します。

イベントハンドラに渡される2つの引数s, eのsはイベントを発生させたオブジェクト、eはイベントの引数(クリックした座標やキーの種類)です。eの内容はイベントの種類によって変わります。

入力に関するクラス(KeyEventArgsクラス、Key列挙体など)は、System.Windows.Input名前空間に含まれています。

インターフェイス要素の作成

Silverlightアプリケーションでは基本的なインターフェイス要素をXAML、マネージコードをIronRuby(あるいは他の言語プラットフォーム)で記述するのが基本スタイルです。

しかし、動的にインターフェイス要素を生成する場合はマネージコードからインターフェイス要素を作成する必要があります。SilverlightではXAMLのほとんどの要素に対して対応するマネージコードが存在します。サンプルをみたほうがわかりやすいと思いますので、紹介します。

 1:  require "lib/silverlight"
 2:  require "mscorlib"
 3:
 4:  class App < SilverlightApplication
 5:    use_xaml(:type => Canvas, :name => "app")
 6: 
 7:    def initialize
 8:      hello.mouse_left_button_down do |s, e|
 9:        newtext = TextBlock.create(:text => "create new object", :font_size => 20)
10:        root.children.add(newtext)
11:        Canvas.set_left(newtext, 100)
12:        Canvas.set_top(newtext, 100)
13:      end
14:    end
15:  end
16:  $app = App.new

10行目はTextBlockオブジェクト新しく生成しています。11行目は生成したオブジェクトを表示領域(root)に結合しています。12行目、13行目は結合したroot内でのnewtextの相対位置を設定しています。

これを実行して、文字をクリックすると下の表示になります。

図2 
図2 

上のサンプルのnewtextと等価なXAMLが以下のコードです。

  <TextBlock Text="create new object" FontSize="20" Canvas.Top="100" Canvas.Left="100" />

ストーリーボードによるアニメーション

ストーリーボードとはSilverlightでの複数のアニメーションをパッケージした要素です。これもサンプルを見る方がわかりやすいですので、XAMLに記述したストーリーボードをマネージコードで動かしてみます。

まず、xamlのroot要素(Canvas)の中に以下のコードを追加します。

<Canvas.Resources>
  <Storyboard x:Name="hello_animation">
    <DoubleAnimation Duration="00:00:03" Storyboard.TargetName="hello" 
                     Storyboard.TargetProperty="(Canvas.Top)" From="0" To="300" 
                     AutoReverse="True" RepeatBehavior="Forever" />
  </Storyboard>
</Canvas.Resources>

そして、マネージコードを次のように記述します。

 1:  require "lib/silverlight"
 2:  require "mscorlib"
 3:
 4:  class App < SilverlightApplication
 5:    use_xaml(:type => Canvas, :name => "app")
 6: 
 7:    def initialize
 8:      @move = true
 9:      hello_animation.begin
10:      hello.mouse_left_button_down do |s, e|
11:        @move ? hello_animation.pause : hello_animation.resume
12:        @move = !@move
13:      end
14:    end
15:  end
16:  $app = App.new

これを動かすと文字列が上下に動いて、文字列をクリックすると停止、もう一度クリックするとまた動き出します。

処理内容は9行目でXAMLに定義したストーリーボードを起動しています。ストーリーボードの内容は3秒(Duration)でテキストが下に300ピクセル分動き、同じ速度で戻ってきます(AutoReverse⁠⁠。この動きを延々繰り返しています(RepeatBehavior⁠⁠。

10行目からのイベントハンドラはテキストをクリックしたときの処理で、ストーリーボードの停止、再開を行います。

本格的なアプリケーションを作るために

クリエイターとの連携

大規模なアプリケーション、特にUIの凝ったものを作るためにはデザイナーとの連携が必須になります。SilverlightではUIにあたる部分がマネージコードから分離されているため、XAMLでのデザイン工程とのマネージコードを使ったシステム開発を比較的スムーズに連携することができます。XAMLのデザインツールとしてはMicrosoft Expressionが利用されています。

前回の記事でXAMLとマネージコードの関係はHTMLとJavaScriptの関係に近いという説明をしましたが、ワークフローの面でも近いといえます。

リソースの管理

SilverlightアプリケーションはリッチなUIを持つので、画像、音声などのコンテンツを多用します。そのため外部に置いたファイルを呼び出すことも多くなりますが、注意点が1点あります。それはSilverlightのxapファイルの呼び出し元によってパスの指定方法が変わる点です。

たとえば、以下のURLにあるSilverlightアプリケーションを呼び出したとします。

http://host/path/xxx.xap

ここから同じドメイン内にある外部ファイルを呼び出すときには、以下のURLが起点となります。

http://host/path/

たとえば、XAMLで外部ファイルのパスに「/image.jpg」と設定すると、⁠http://host/path/image.jpg」と解釈されます。http://host/image.jpgを呼び出したい場合は「http://host/image.jpg」と記述する必要があります。

SilverStarプラグインではリソース管理用にpublic/resourcesディレクトリを自動的に作成します。これはSilverlight用の素材データをresources以下に配置して、mod_rewriteでresources以下に変換することを想定しています。

本番環境

SilverStarプラグインはxamlのレンダリング、マネージコードとの結合、xapデータの生成をアクセス時に実行するため、本番環境ではかなり重い処理になってしまいます。

そのため、生成したxapデータはキャッシュする必要があります。最も簡単な方法はRailsのページキャッシュ機構をそのまま適用することです。

  class SilverlightController < ApplicationController
    caches_page
 
    # methods
  end

これだけで生成したxapデータを静的ファイルとして保存できます。

最適化

本番環境ではパフォーマンスが求められます。IronRubyで生成したクラスオブジェクトとSilverlight内のインターフェイス要素では、現在のバージョンではアクセス速度に差があります。動きの多いフレーム処理を行うような場合はこのような点を考慮して実装する必要があります。

どうしてもパフォーマンスが出ない場合はより高速な言語を使って実装する必要性が出てくるかもしれません。ライブラリが共通なので、こういった場合の移植性は高いといえるでしょう。

おわりに

以上がSilverlightの簡単なアプリケーションを作れるまでの説明になります。

Silverlightにはここでは紹介できなかった機能がまだ多くあります。IronRubyはまだβ版ですが、正式版に向けて積極的にメンテナンスされています(2009年8月に最新版0.9.0がリリースされました⁠⁠。多くの可能性を持ったプラットフォームだと思いますので、読者の方にもぜひ実際に動かしてみていただきたいです。

最後にSilverlightとRuby on Railsを使った今回のサンプルより、一歩進んだアプリケーションの紹介をしておきます。

こちらはSilverlightとRuby on Railsを利用した簡単なゲームアプリケーションです。mixiプラットフォーム上で動くので以下の手順でお試しください。

  1. mixiアプリ オープンβコミュニティに参加します
  2. mixiアプリを使用する専用アドレスでログインします
  3. アプリ紹介ページからアプリを登録します
  4. 登録したらアプリを起動します

おすすめ記事

記事・ニュース一覧