突破してみる? / Why don't you get over?

ソフトウェアエンジニアの備忘録 / Memorandum for software engineers

CoffeeScriptでオブジェクト指向

JQueryをつかってHTML5のオーディオAPIで遊んでみよう

<!DOCTYPE html>
<html>
  <head>
    <script src='./jquery-2.1.1.min.js'></script>
    <script src='./player_jquery.js'></script>
  </head>
  <body>
    <audio controls id='player'>
      <source src='./test.mp3'></source>
    </audio>
    <div id='controller'>
      <input id='speed_slider' max='3' min='0.1' step='0.1' type='range' value='1'>
      <input id='speed_ratio' max='3' min='0.1' step='0.1' type='number' value='1'>
    </div>
  </body>
</html>
change_playback_rate = (speed) ->
  $('audio#player')[0].playbackRate = speed # HTML5 Audio API

$(document).ready ->
  $('input#speed_slider').on 'input', (event) ->
    speed = event.target.value
    $('input#speed_ratio').val(speed)
    change_playback_rate(speed)

  $('input#speed_ratio').on 'input', (event) ->
    speed = event.target.value
    $('input#speed_slider').val(speed)
    change_playback_rate(speed)

CoffeeScriptコンパイルはこうなります。

$ coffee -c player_jquery.coffee
$

test.mp3は、適宜用意してください。
player_jquery.htmlをブラウザで見ると、HTML5オーディオプレイヤとスライダと数値ボックスが表示されます。スライダか数値の変更により、オーディオの再生速度が変わります。

$(document).ready()節にイベント処理を実装して全体でコードを短くしてみました。

オブジェクト指向CoffeeScriptに書き換えよう

  • player_class.html
<!DOCTYPE html>
<html>
  <head>
    <script src='./jquery-2.1.1.min.js'></script>
    <script src='./player_class.js'></script>
  </head>
  <body>
    <audio controls id='player'>
      <source src='./test.mp3'></source>
    </audio>
    <div id='controller'>
      <input id='speed_slider' max='3' min='0.1' step='0.1' type='range' value='1'>
      <input id='speed_ratio' max='3' min='0.1' step='0.1' type='number' value='1'>
    </div>
  </body>
</html>
  • player_class.coffee
class Player
  tag_audio: 'audio#player'

  constructor: ->
    @audio = $(@tag_audio)[0] # Get DOM of the audio tag from the JQuery object

  change_playback_rate: (speed) =>
    @audio.playbackRate = speed # HTML5 Audio API

class Controller
  tag_speed_slider: 'input#speed_slider'
  tag_speed_ratio:  'input#speed_ratio'

  constructor: (player) ->
    @player = player
    @speed_slider = $(@tag_speed_slider)
    @speed_ratio  = $(@tag_speed_ratio)
    
    @register_events()

  register_events: =>
    @speed_slider.on
      input: @on_update_speed_slider
    @speed_ratio.on
      input: @on_update_speed_ratio

  on_update_speed_slider: (event) =>
    speed = event.target.value
    @speed_ratio.val(speed)
    @player.change_playback_rate(speed)

  on_update_speed_ratio: (event) =>
    speed = event.target.value
    @speed_slider.val(speed)
    @player.change_playback_rate(speed)


$(document).ready ->
  player = new Player
  new Controller(player)

CoffeeScriptコンパイルはこうなります。

$ coffee -c player_class.coffee
$

test.mp3は、適宜用意してください。
player_class.htmlをブラウザで見ると、同じようにHTML5オーディオプレイヤとスライダと数値ボックスが表示されます。スライダか数値の変更により、オーディオの再生速度が変わります。

Playerは、HTML5のオーディオAPIを扱うクラスとしました。
Controllerは、スライダとスピードレシオのウィジェットとイベントを扱うクラスとしました。
イベントハンドラの登録は、register_events()内で行い、コンストラクタから呼ばれます。

$(document).ready()節でインスタンスを生成して、その節のコードを短くしてみました。

オブジェクト指向での利点

各クラスでタグのセレクタを宣言的に定義しました。それにより、コード内でJQueryコールのたびにセレクタが散らばらなくなります。
イベントハンドラの実装は、クラスのインスタンスメソッドとして宣言的に定義して、文脈を明確にしてみました。

PlayerとControllerを分けることで、HTML5オーディオAPIウィジェット/イベントが疎結合になったと思います。