1. Qiita
  2. 投稿
  3. Opal

OpalでJavaScriptのAPIを呼びだしてみよう

  • 0
    いいね
  • 0
    コメント

    この記事はOpal Advent Calendar 2016の9日目の投稿として書いています。

    またしても日付を超えてしまいましたが、今日はOpalからJavaScriptのAPIを呼びだしてみようと思います。
    OpalはRubyからJavaScriptへソースコードを変換するコンパイラです。なので基本的にはRubyでプログラムを書くことになります。
    Opalのエコシステムが充実してきているとはいえ、やはりそれだけでは足りないこともあります。
    JavaScriptを直接実行することができれば、プラットフォームやライブラリで提供されるAPIを呼びだすことができます。
    もっとも簡単な方法は、`で囲まれた中にJavaScriptのコードを書くことです。

    例えば、

    `alert('hello world')`
    

    のように書きます。
    複数行あるような場合は%x記法でも書けます。

    %x(
      var str = 'hello world';
      alert(str);
    )
    

    アラートだけではつまらないのでもうすこし実用的なプログラムにしましょう。
    Web Audioを使って音を鳴らすなんでどうでしょう。Qiitaで検索すると適当なサンプルがありますね。
    http://qiita.com/ykob/items/462b558192ab09500bf3

    昨日紹介したsilicaで作ったプロジェクトに埋めこんでみましょう。
    app/application.rbを以下のように書きかえます。

    app/application.rb

    require 'hyalite'
    #require 'menilite'
    
    class AppView
      include Hyalite::Component
    
      def play
        %x(
          var context = new AudioContext();
          var buffer = null;
          var source = context.createBufferSource();
    
          var request = new XMLHttpRequest();
          request.open('GET', 'assets/sounds/sample.mp3', true);
          request.responseType = 'arraybuffer';
          request.send();
    
          request.onload = function () {
            var res = request.response;
            context.decodeAudioData(res, function (buf) {
              source.buffer = buf;
            });
          };
          source.connect(context.destination);
          source.start(0);
        )
      end
    
      def render
        div(nil,
          button({onClick: self.method(:play)}, 'Play')
        )
      end
    end
    Hyalite.render(Hyalite.create_element(AppView), $document['.content'])
    

    mp3ファイルをassets/soundsというディレクトリを作ったその下にsample.mp3という名前で置いてください。
    mp3ファイルはご自身でご用意くださいね。

    Playボタンを押してみてください。サウンドが鳴りましたでしょうか?

    さて、これでいつでもJavaScriptを実行できるので、Opalの上でなんでもできることになります。
    しかし、せっかくRubyで書けるのに埋め込みのJavaScriptで埋めつくされるのも残念な感じです。JavaScriptからまたRubyに戻ってくる必要がありますね。
    そこでOpalにはNativeという機能が用意されています。

    require 'native'して、AudioContextを以下のように作成します。

      context = Native(`new AudioContext()`)
    

    先ほどの説明のとおり、`に囲まれたところはJavaScriptのコードになります。
    Native()Native::Object.new()と同じ意味でNativeオブジェクトを作ることになります。
    NativeオブジェクトはRubyのメソッド呼び出しとしてJavaScriptのメソッドを呼びだすことができます。

      source = context.createBufferSource
    

    このように、JavaScriptで作られたオブジェクトをNativeオブジェクトでRuby側で自由にあつかうことができるようになります。

    playメソッドはつぎのように書きかえることができます。

      def play
        context = Native(`new AudioContext()`)
        source = context.createBufferSource
    
        request = Native(`new XMLHttpRequest()`)
        request.open('GET', 'assets/sounds/sound.mp3', true)
        request.responseType = 'arraybuffer'
        request.send
    
        request.onload = Proc.new do
          res = request.response
          context.decodeAudioData(res) do |buf|
            source.buffer = buf
          end
        end
        source.connect(context.destination)
        source.start(0)
      end
    

    JavaScriptのfunctionはRubyのProcオブジェクトやブロックで置きかえることができます。

    どうでしょうかサウンドは鳴りましたか?

    このようにNativeを使えばJavaScriptのオブジェクトをラップすることができます。明日は(というってももう日付が変ってしまいましたが)Web Audioを便利に扱えるライブラリを作ってみましょう。

    この投稿は Opal Advent Calendar 20169日目の記事です。
    Comments Loading...