HTML5ビデオを管理するためのjQueryプラグインを作成しています。 canplayイベントとcanplaythroughイベントをキャプチャしようとしています。 Chromeでは、イベントは問題なく発生します。 Firefoxでは、トリガーされる場合とトリガーされない場合があります。
ここでコードを少し単純化しています:
$('#my_video').on('canplay canplaythrough', function(){
console.log('canplay event fired');
});
また、ネイティブjavascript .addEventListener()を試しましたが、動作しません。
Firefoxでイベントが呼び出されない理由と、それを修正する方法はありますか?
注:jplayerやvideo-jsのような既に利用可能なプラグインの1つを使用するように言わないでください。それらが存在し、うまく機能することは知っていますが、社内ソリューションを構築する必要があります。
問題は、イベントハンドラを登録する前に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();
}
これが表示される最も可能性の高い理由は、おそらくタイミングの問題に関係しています。受け入れられた回答の中で、フッターではなくjQueryを頭に入れると問題が解決すると述べました。これは、問題がDOM解析とスクリプト実行順序であることを教えてくれます。最も可能性の高い犯人は、jqueryとページスクリプトが解析され、イベントハンドラーが追加される前に「canplay」イベントと「canplaythrough」イベントが発生したことです。スクリプトを先頭に置くことで、DOM要素が作成される前にイベントバインディングを強制的に実行し、イベントを見逃さないようにしました。
余談ですが、スクリプト要素をページの下部に配置することによるパフォーマンス上の利点は議論の余地があります。ページのパフォーマンスを本当に調整したい場合は、LABjsのようなものを使用して、並列スクリプトの読み込みを管理します。
私の質問がまったく注目されなかったとしても、将来これにつまずくかもしれない人々に説明をするのは良い考えだと思います...
問題は本当に奇妙です。jQueryコアがフッターに含まれていると、ビデオイベントの一部が機能しません。 jQueryコアがドキュメントのヘッドに含まれている場合、すべてのイベントが正しく呼び出されます。
そのため、最適化のための「ベストプラクティス」では、読み込み時間を短縮するためにすべてのスクリプトを本文の最後に配置することが推奨されている場合でも、jQueryコアをHTMLヘッドに含めることです。
また、これは競合状態だと思います。私がそれを回避した方法は次のとおりです:
動画要素の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-他の場所でテストされていません。
load
をトリガーした後にFirefoxがオーディオ全体をロードすると予想する場合、これは実行されません。 loadstart
を起動しますが、何もダウンロードしません。 progress
イベントは発生しません。そして、実際にはそのファイルへの要求は行いません。この動作はFirebugで確認できます。
Firefoxは、「play」をトリガーした後にのみファイルの読み込みを開始します。
証明 。コンソール出力を参照してください。
私の場合、これは要素に指定されたpreload
属性によって決定されました。私はそれをまったく指定していなかったので、異なるブラウザが異なることをすることを選択していました。
_preload="auto"
_を指定すると、on("canplay")
イベントハンドラーは期待どおりに正常に機能しました。
ここ(バニラ)からさまざまなアプローチを試した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)
}
}
追加:
var video = $('video');
video.trigger('load');
After canplaythroughイベントリスナーを追加すると、FirefoxとSafariで修正されました。