6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

FRP で YouTube のモーダルスクリーンを実装してみる。

Last updated at Posted at 2015-03-20

YouTube の Player API で YouTube 動画のモーダルスクリーンを実装する機会があったので、Bacon.js で実装してみたメモ。

全体のコードはこんな感じ:

(function (w, d, $, B) {

  // YouTube Player API の読み込み関数
  var youtubePlayerAPI = function (cb) {
    var el = d.createElement('script'), topEl = d.getElementsByTagName('script')[0];
    el.src = 'https://www.youtube.com/iframe_api';
    w.onYouTubeIframeAPIReady = function () { cb(w.YT); };
    topEl.parentNode.insertBefore(el, topEl);
  };

  // YouTube プレイヤのコンストラクタ関数
  var createYoutubePlayer = function (YT, selectorId, videoId, cb) {
    return new YT.Player(selectorId, {
      videoId: videoId,
      width: 320,
      height: 180,
      playerVars: {
        controls: 1,
        loop: 1,
        rel: 0,
        showinfo: 0,
        wmode: 'transparent'
      },
      events: { onReady: cb }
    });
  };
  
  // YouTube API 読み込み完了を待つストリーム
  var youtubeAPIReady = B.fromCallback(youtubePlayerAPI);
  // DOM 読み込み完了を待つストリーム
  var contentLoaded = B.fromCallback($(d).ready);
  // 上記 2 つの読み込み完了を待つストリーム
  var ready = B.combineWith(function (content, api) { return api }, contentLoaded, youtubeAPIReady);

  // 上記ストリームの読み込み完了タイミングで実行されるリスナ
  ready.onValue(function (YT) {
    var $open = $('#open'), $close = $('#close'), $layer = $('#layer'), $main = $('#main');

    // 個別 YouTube 動画の読み込み完了を待つストリームバインダ
    var videoBinder = function (selectorId, videoId) {
      return function (sink) {
        createYoutubePlayer(YT, selectorId, videoId, function (ev) {
          sink(ev.target);
          sink(new B.End());
        });
      };
    };

    // 上記バインダを利用したストリーム
    var playerReady = B.fromBinder(videoBinder('player', 'DVwHCGAr_OE'));
    
    // モーダルを開くリンクのクリック監視をするストリーム
    var openClick = $open.asEventStream('click').doAction('.preventDefault');
    // 上記開くリンクのトリガと YouTube 動画読み込み完了を待つストリーム
    var open = openClick.combine(playerReady, function (click, player) { return player; });
    
    // モーダルを閉じるリンクのクリック監視をするストリームプロパティ
    var closeClick = $close.asEventStream('click').doAction('.preventDefault').toProperty(w.event);
    // モーダル背景のクリック監視をするストリームプロパティ
    var layerClick = $layer.asEventStream('click').toProperty(w.event);
    // 上記 2 つどちらかのトリガを監視するストリームプロパティ
    var closeOrLayerClick = closeClick.or(layerClick);
    // 上記トリガと YouTube 動画読み込み完了を待つストリーム
    var close = closeOrLayerClick.combine(playerReady, function (click, player) { return player; });
    
    // 開く処理がトリガされた時に実行されるリスナ
    open.onValue(function (player) {
      $layer.css({ display: 'block' });
      $main.css({ display: 'none' });
      player.playVideo();
    });

    // 閉じる処理がトリガされた時に実行されるリスナ
    close.onValue(function (player) {
      player.stopVideo();
      $layer.css({ display: '' });
      $main.css({ display: '' });
    });
  });

})(window, document, jQuery, Bacon);

様々な非同期処理を、ストリームという時系列に値が push されていく無限配列のようなオブジェクトに、Underscore.js のような配列操作で、様々な処理を書いていけるのが FRP っていうのが、今の認識。

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?