YT.Player 没有 return 带有 playVideo() 的实例
YT.Player doesn't return an instance with playVideo()
当我创建 YT.Player(HTMLIFrameElement, { options })
的实例时,我得到一个对象,该对象具有:
- 摧毁
- 设置大小
- getIframe
- 添加事件监听器
- getVideoEmbedCode
- 获取选项
- 获取选项
但不是 playVideo
、pauseVideo
等,如 documentation 中所述。
我在这里有一个演示:http://siesta-annotations.surge.sh/Siesta_webviewer_test/?page=3
我正在通过 trait.playable.youtube.js
中的 DOM 创建 iframe,并将 iframe 添加到 documentFragment
,最终将添加到 div:
const element = document.createElement('iframe')
element.src = `https://www.youtube.com/embed/${id}?rel=0;&autoplay=${this.options.autostart ? 1 : 0};&enablejsapi=1;&origin=${location.hostname};`
element.style = this.inlineStyle
然后我创建了一个实例 YT.Player:
// nasty initialization because we're outside webpack and this is a demo
if (global.YT.loaded) {
this.player = new global.YT.Player(element, {
events: {
'onStateChange': this.stateHandler,
'onReady': onPlayerReady
}
})
} else {
const oldHandler = global.onYouTubeIframeAPIReady
global.onYouTubeIframeAPIReady = () => {
if (oldHandler) oldHandler()
this.player = new global.YT.Player(element, {
events: {
'onStateChange': this.stateHandler,
'onReady': onPlayerReady
}
})
}
}
YT.Player 的实例看起来像这样:
看起来缩小过程出错了。我做错了什么 - 我应该如何为我的用例初始化 YT.Player?
奇怪的是,在构造函数播放器选项对象中调用 'onReady'
之前,您无法访问 YTPlayer API。 https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player
function onYouTubeIframeAPIReady() {
new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': function (event) {
onPlayerReady(event.target)
},
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(player) {
player.playVideo();
}
这当然只适用于一个播放器,因此如果您想处理多个播放器,则需要推出自己的 YouTube 播放器管理器。 (我知道 API 疯了)
如果您的 iframe 包含 YouTube 视频(未测试),可以采用以下快速解决方案:
const YTManager = {
videos: [],
youtubeApiReady = false,
initialize () {
const matchId = /[^/]+$/
this.youtubeApiReady = true
document.querySelectorAll('iframe[src*="youtube"]')
.forEach(iframe => this.videos.push({
dom: iframe,
player: null,
videoId: iframe.src.exec(matchId) || iframe.src.exec(matchId)[0]
}))
},
createPlayers () {
if (this.youtubeApiReady === false) return
this.videos.forEach(v => {
new YT.Player(v.dom.id, {
videoId: v.videoId,
events: {
'onReady': function (event) {
v.player = event.target
}
}
})
})
},
find (id) {
return this.videos.find(v => v.id === id)
},
play (id) {
const video = this.find(id)
if (this.youtubeApiReady && video && video.player) {
video.playVideo()
}
},
pause (id) {
const video = this.find(id)
if (this.youtubeApiReady && video && video.player) {
video.pauseVideo()
}
},
}
window.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady() {
// YouTube client side script has been loaded
YTManager.youtubeApiReady = true
YTManager.createPlayers()
}
document.addEventListener("DOMContentLoaded", function() {
// all iframes has been parsed by the browser
YTManager.initialize()
});
当然你不能在没有ID的情况下调用YTManager.play
或YTManager.pause
并等待YouTube脚本加载然后视频初始化完成。总而言之,真是一团糟。我相信你能想出一个更好的经理。我在工作中写过一个更好但也适用于完全不同的对象和要求,因此它不太适合通用 YouTube 视频管理器。不过上面那个是我现在播放器的要点
我建议从一开始就使用 iframe - 如果您的脚本出现任何问题,视频仍然可以播放,只是您无法控制它们。
Iframed YouTube 视频如下所示:
<iframe
id="uniqueDOMElementID1"
width="560"
height="315"
src="https://www.youtube.com/embed/bHQqvYy5KYo"
frameborder="0"
allow="autoplay; encrypted-media"
allowfullscreen></iframe>
这是我的第二篇post,希望能解决您的问题。
我不是 100% 确定你的代码是如何工作的,但我怀疑......
It seems like a double instantiation of the YT.Player
object, which will cause the YT.Player
object unstable.
我自己也奋斗了很久(ps:我是业余程序员。)
例如,以下代码段修改自 Youtube Iframe API website and an example of how the second instantiation will break the player object try it! JS Bin:
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
</br>
<button onclick="instantiateOneMore()">
Call
<pre>new YT.Player('player')</pre>
</button>
<button onclick="pauseVideo()">
pauseVideo();
</button>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
let callTime = 0;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
callTime ++;
console.log(callTime);
//document.querySelector('#dd').innerHTML = player.pauseVideo;
}
function pauseVideo(){
player.pauseVideo();
}
instantiateOneMore = () => {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
//document.querySelector('#dd').innerHTML = player.pauseVideo;
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
/* setTimeout(stopVideo, 6000) */
;
done = true;
}
}
/*
function stopVideo() {
player.stopVideo();
} */
</script>
</body>
</html>
此外,第二个 onPlayerReady()
甚至不会被调用。因此,如果您打算放置一些计数器来查看 new YT.Player(...)
被调用了多少次,您会怀疑它只被调用了一次。这使得效果远离调试。
当我创建 YT.Player(HTMLIFrameElement, { options })
的实例时,我得到一个对象,该对象具有:
- 摧毁
- 设置大小
- getIframe
- 添加事件监听器
- getVideoEmbedCode
- 获取选项
- 获取选项
但不是 playVideo
、pauseVideo
等,如 documentation 中所述。
我在这里有一个演示:http://siesta-annotations.surge.sh/Siesta_webviewer_test/?page=3
我正在通过 trait.playable.youtube.js
中的 DOM 创建 iframe,并将 iframe 添加到 documentFragment
,最终将添加到 div:
const element = document.createElement('iframe')
element.src = `https://www.youtube.com/embed/${id}?rel=0;&autoplay=${this.options.autostart ? 1 : 0};&enablejsapi=1;&origin=${location.hostname};`
element.style = this.inlineStyle
然后我创建了一个实例 YT.Player:
// nasty initialization because we're outside webpack and this is a demo
if (global.YT.loaded) {
this.player = new global.YT.Player(element, {
events: {
'onStateChange': this.stateHandler,
'onReady': onPlayerReady
}
})
} else {
const oldHandler = global.onYouTubeIframeAPIReady
global.onYouTubeIframeAPIReady = () => {
if (oldHandler) oldHandler()
this.player = new global.YT.Player(element, {
events: {
'onStateChange': this.stateHandler,
'onReady': onPlayerReady
}
})
}
}
YT.Player 的实例看起来像这样:
看起来缩小过程出错了。我做错了什么 - 我应该如何为我的用例初始化 YT.Player?
奇怪的是,在构造函数播放器选项对象中调用 'onReady'
之前,您无法访问 YTPlayer API。 https://developers.google.com/youtube/iframe_api_reference#Loading_a_Video_Player
function onYouTubeIframeAPIReady() {
new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': function (event) {
onPlayerReady(event.target)
},
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(player) {
player.playVideo();
}
这当然只适用于一个播放器,因此如果您想处理多个播放器,则需要推出自己的 YouTube 播放器管理器。 (我知道 API 疯了)
如果您的 iframe 包含 YouTube 视频(未测试),可以采用以下快速解决方案:
const YTManager = {
videos: [],
youtubeApiReady = false,
initialize () {
const matchId = /[^/]+$/
this.youtubeApiReady = true
document.querySelectorAll('iframe[src*="youtube"]')
.forEach(iframe => this.videos.push({
dom: iframe,
player: null,
videoId: iframe.src.exec(matchId) || iframe.src.exec(matchId)[0]
}))
},
createPlayers () {
if (this.youtubeApiReady === false) return
this.videos.forEach(v => {
new YT.Player(v.dom.id, {
videoId: v.videoId,
events: {
'onReady': function (event) {
v.player = event.target
}
}
})
})
},
find (id) {
return this.videos.find(v => v.id === id)
},
play (id) {
const video = this.find(id)
if (this.youtubeApiReady && video && video.player) {
video.playVideo()
}
},
pause (id) {
const video = this.find(id)
if (this.youtubeApiReady && video && video.player) {
video.pauseVideo()
}
},
}
window.onYouTubeIframeAPIReady = function onYouTubeIframeAPIReady() {
// YouTube client side script has been loaded
YTManager.youtubeApiReady = true
YTManager.createPlayers()
}
document.addEventListener("DOMContentLoaded", function() {
// all iframes has been parsed by the browser
YTManager.initialize()
});
当然你不能在没有ID的情况下调用YTManager.play
或YTManager.pause
并等待YouTube脚本加载然后视频初始化完成。总而言之,真是一团糟。我相信你能想出一个更好的经理。我在工作中写过一个更好但也适用于完全不同的对象和要求,因此它不太适合通用 YouTube 视频管理器。不过上面那个是我现在播放器的要点
我建议从一开始就使用 iframe - 如果您的脚本出现任何问题,视频仍然可以播放,只是您无法控制它们。
Iframed YouTube 视频如下所示:
<iframe
id="uniqueDOMElementID1"
width="560"
height="315"
src="https://www.youtube.com/embed/bHQqvYy5KYo"
frameborder="0"
allow="autoplay; encrypted-media"
allowfullscreen></iframe>
这是我的第二篇post,希望能解决您的问题。
我不是 100% 确定你的代码是如何工作的,但我怀疑......
It seems like a double instantiation of the
YT.Player
object, which will cause theYT.Player
object unstable.
我自己也奋斗了很久(ps:我是业余程序员。)
例如,以下代码段修改自 Youtube Iframe API website and an example of how the second instantiation will break the player object try it! JS Bin:
<!DOCTYPE html>
<html>
<body>
<!-- 1. The <iframe> (and video player) will replace this <div> tag. -->
<div id="player"></div>
</br>
<button onclick="instantiateOneMore()">
Call
<pre>new YT.Player('player')</pre>
</button>
<button onclick="pauseVideo()">
pauseVideo();
</button>
<script>
// 2. This code loads the IFrame Player API code asynchronously.
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
// 3. This function creates an <iframe> (and YouTube player)
// after the API code downloads.
var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
let callTime = 0;
// 4. The API will call this function when the video player is ready.
function onPlayerReady(event) {
event.target.playVideo();
callTime ++;
console.log(callTime);
//document.querySelector('#dd').innerHTML = player.pauseVideo;
}
function pauseVideo(){
player.pauseVideo();
}
instantiateOneMore = () => {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: 'M7lc1UVf-VE',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
//document.querySelector('#dd').innerHTML = player.pauseVideo;
}
// 5. The API calls this function when the player's state changes.
// The function indicates that when playing a video (state=1),
// the player should play for six seconds and then stop.
var done = false;
function onPlayerStateChange(event) {
if (event.data == YT.PlayerState.PLAYING && !done) {
/* setTimeout(stopVideo, 6000) */
;
done = true;
}
}
/*
function stopVideo() {
player.stopVideo();
} */
</script>
</body>
</html>
此外,第二个 onPlayerReady()
甚至不会被调用。因此,如果您打算放置一些计数器来查看 new YT.Player(...)
被调用了多少次,您会怀疑它只被调用了一次。这使得效果远离调试。