とある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>'
};
});