26

我正在构建一个用于管理 HTML5 视频的 jQuery 插件。我正在尝试捕获 canplay 和 canplaythrough 事件。在 Chrome 中,事件被触发没有问题。在 Firefox 中,有时会触发,有时不会。

我在这里稍微简化了我的代码:

$('#my_video').on('canplay canplaythrough', function(){
    console.log('canplay event fired');
});

我也尝试使用本机 javascript .addEventListener() 但它不起作用。

知道为什么没有在 Firefox 上调用该事件以及如何解决这个问题吗?

注意:请不要告诉我使用已经可用的插件之一,如 jplayer 和 video-js,我知道它们存在并且运行良好,但我必须构建一个内部解决方案。

4

8 回答 8

52

问题是您的元素在您注册事件处理程序之前video触发了事件。canplaythrough

正如您在自己的答案中指出的那样,您可以将脚本放在 中<head>,但这对您的页面性能不利。

解决问题的更好方法是检查readystate属性并在这种情况下手动执行函数:

var $video = $('video'),
    videoElement = $video[0];

$video.on('canplaythrough', callback);

// If the video is in the cache of the browser,
// the 'canplaythrough' event might have been triggered
// before we registered the event handler.
if (videoElement.readyState > 3) {
  callback();
}
于 2014-09-25T09:01:42.003 回答
11

您看到此问题的最可能原因可能与时间问题有关。您在接受的答案中表示,将 jQuery 放在头部而不是页脚可以解决问题。这告诉我问题在于 DOM 解析和脚本执行顺序。最可能的罪魁祸首是“canplay”和“canplaythrough”事件在 jquery 和您的页面脚本被解析并添加事件处理程序之前被触发 - 但只是有时,取决于网络流量和加载时间。通过将脚本放在头部,您强制在创建 DOM 元素之前发生事件绑定,从而确保您不会错过任何事件。

顺便说一句,将脚本元素放在页面底部的性能优势值得商榷。如果您真的想调整页面性能,请使用 LABjs 之类的东西来管理并行脚本加载。

于 2012-11-12T23:45:10.810 回答
7

就我而言,这是由preload为元素指定的属性确定的。我根本没有指定它,所以不同的浏览器选择做不同的事情。

一旦我指定preload="auto"on("canplay")事件处理程序就可以正常/按预期工作。

于 2015-10-22T20:46:31.230 回答
4

即使我的问题没有引起任何关注,我认为为将来可能偶然发现此问题的人提供解释是个好主意...

问题真的很奇怪:如果 jQuery 核心包含在页脚中,则某些视频事件不起作用。如果 jQuery 核心包含在文档的头部,则所有事件都被正确调用。

所以解决方案是在 html 头部包含 jQuery 核心,即使优化的“最佳实践”建议将所有脚本放在正文的末尾以加快加载时间。

于 2012-04-24T19:41:35.890 回答
3

我也确实认为这是一个竞争条件。我绕过它的方式如下:

在视频元素的 HTML 中添加属性 preload="metadata" - 仅预加载视频元数据。所以:

<video id="myVideo" width="640" height="480" preload="metadata" />

接下来,在 JS 内部:

var $vid = $("#myVideo");
$vid.bind("canplaythrough", console.log("can play through full video"));
$vid.get(0).load();

这在 Chrome 中为我记录了消息-尚未在其他地方进行测试。

于 2013-06-07T16:31:08.593 回答
3

如果您希望 Firefox 在触发后加载整个音频,load那么它不会这样做。它会触发loadstart但不会下载任何东西。progress不会触发任何事件。它实际上不会对该文件提出任何请求。您可以在 Firebug 中看到这种行为。

Firefox 只会在您触发“播放”后开始加载文件。

证明。请参阅控制台输出。

于 2014-10-17T18:06:09.930 回答
1

添加:

var video = $('video');
video.trigger('load');

添加 canplaythrough 事件侦听器后,我在 Firefox 和 Safari 上修复了它。

于 2015-01-07T19:07:55.513 回答
1

经过 1.5 天从这里尝试不同的方法(香草)。带有 addEventListner 的事件“canplay”和“canplaythrough”在 Edge 中不起作用。它们在其他所有浏览器中都能正常工作。所以我最后用 setTimout 检查了“就绪状态”:-(。不是很优雅,但它对我有用。

Controller.prototype.backGroundControl = function () {
var vid = document.querySelector('#bgvid');
var bgImg = document.querySelector('#bgimg');
_this = this;

if (vid.readyState === 4){
    bgImg.style.opacity = "0"
} else{
    setTimeout(function(){
        _this.backGroundControl();
    },500)
}  

}

于 2017-05-23T09:26:30.947 回答