LoginSignup
10
11

More than 5 years have passed since last update.

YouTube Player APIで動画を埋め込むAngularディレクティブを作成する

Posted at

とあるAngularを使用しているプロジェクトで、YouTubeの動画を埋め込むことタスクがあったのだが、その際にちょっとハマったのでメモ。

とりあえず手っ取り早くYouTubeが提供しているAPIを使用。
iframe組み込みのYouTube Player APIについてはこちら
https://developers.google.com/youtube/iframe_api_reference?hl=ja

素のJSで書いた場合

普通に書くなら下記になる。

<div id="player"></div>
<script>
  var tag = document.createElement('script');
  tag.src = "https://www.youtube.com/iframe_api";
  var firstScriptTag = document.getElementsByTagName('script')[0];
  firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

  var player;
  function onYouTubeIframeAPIReady() {
    player = new YT.Player('player', {
      height: '390',
      width: '640',
      videoId: 'M7lc1UVf-VE',
      events: {
        'onReady': onPlayerReady,
        'onStateChange': onPlayerStateChange
      }
    });
  }

  function onPlayerReady(event) {
    // event.target.playVideo();
  }

  function onPlayerStateChange(event) {
    if (event.data == YT.PlayerState.ENDED) {
      alert('finished');
    }
  }
  function stopVideo() {

  }
</script>

Angularで書いた場合

今回はAngular使ってるので、下記のようなディレクティブを作成する。

    var myApp = angular.module('myApp', []);

    myApp.directive('youtube', function(){

      var _link = function(scope, element, attr){

        var tag = document.createElement('script');
        tag.src = "https://www.youtube.com/iframe_api";
        var firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

        var player;

        function onYouTubeIframeAPIReady() {

          player = new YT.Player(element.children()[0], {
            height: scope.width,
            width: scope.height,
            videoId: scope.youtubeId,
            events: {
              'onStateChange': function(event){
                if (event.data == YT.PlayerState.ENDED){
                  alert('finished!!');
                }
              }
            }
          });
        }

      };

      return {
        link: _link,
        scope: {
          width: "@",
          height: "@",
          youtubeId: "@"
        },
        restrict: 'E',
        template: '<div></div>'
      };
    });

htmlは下記の1行を追加

<youtube width="640" height="390" youtube-id="M7lc1UVf-VE"></youtube>

これでいけるかと思ったが、YouTubeのライブラリを読み込んだ後に実行されるonYouTubeIframeAPIReadyが発火せず・・

ググっていると下記記事を発見。
http://stackoverflow.com/questions/12256382/youtube-iframe-api-not-triggering-onyoutubeiframeapiready

onYouTubeIframeAPIReady関数はグローバルにしないといけないらしいので、$windowを引数に渡して、

$window.onYouTubeIframeAPIReady = function(){}

に修正したところ、動きました。

最終的なコードは下記のとおり。

    var myApp = angular.module('myApp', []);

    myApp.directive('youtube', function($window){

      var _link = function(scope, element, attr){

        var tag = document.createElement('script');
        tag.src = "https://www.youtube.com/iframe_api";
        var firstScriptTag = document.getElementsByTagName('script')[0];
        firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

        var player;

        $window.onYouTubeIframeAPIReady = function() {

          player = new YT.Player(element.children()[0], {
            height: scope.width,
            width: scope.height,
            videoId: scope.youtubeId,
            events: {
              'onStateChange': function(event){
                if (event.data == YT.PlayerState.ENDED){
                  alert('finished!!');
                }
              }
            }
          });
        }

      };

      return {
        link: _link,
        scope: {
          width: "@",
          height: "@",
          youtubeId: "@"
        },
        restrict: 'E',
        template: '<div></div>'
      };
    });

10
11
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
10
11