Help us understand the problem. What is going on with this article?

PC版U-NEXTの動画視聴のストレスを減らすスクリプトを書いたメモ

ビギナーです(免罪符)。
U-NEXTにおいて動画画面クリックで再生/一時停止操作を可能にするスクリプトを書きました。
配布先はこちら

はじめに

youtubeでは動画画面上をクリックで再生/一時停止が切り替えられます。U-NEXTはそれができず、ながら見しているときに動画を一時停止したいときは毎回画面左下にある2cm四方くらいのボックスにマウスカーソルをピタリと当てる必要があります。私はエイム練習がしたくて動画を見ているわけではないのです...これはストレスです。

U-NEXTの仕様と思惑・失敗

 U-NEXTの動画再生ページでは多くのhtmlタグがネストされています。chromeのデベロッパーツールで探ってみたところ、UIレイヤーの一番上にくるタグはdivで、class="ezLrGS"ないしマウスホバー時は"feUiJR"を持っていることがわかりました。そこでそのdivに対しオンクリックイベントを仕掛け、再生/一時停止を可能にしようと試みました。
ところがそのdivは、シークバーや音量調整などの動画のコントロール全般のオンクリックを担っているようなのです。コントロールバーはボタンそれぞれ別個にdivで領域確保されていて上にレイヤードされているのに、それらのマウスクリックイベントが透過しているような感じです。現に、件のレイヤーのdivのクリックをCSSで透過させると、クリックでは何も操作できなくなりました。
 そこで、この記事に着想を得ました。コントロールバーや、次の動画のホバーがあるタイトル付近を避けて新しくdivをマスクし、そこにオンクリックを付加するというアイデアです。この方向性でうまく動作させることが可能となりました。

スクリプト本体・説明

// ==UserScript==
// @name         PlayPauseOnScreen-UNEXT
// @description  Enable you to play or pause a movie with a click on the screen at U-NEXT
// @version      1.4
// @namespace    https://qiita.com/toten_s
// @match        https://video.unext.jp/*
// ==/UserScript==

function addGlobalStyle(css){
  var head, style;
  head = document.getElementsByTagName("head")[0];
  if (!head) { return }
  style = document.createElement("style");
  style.type = "text/css";
  style.innerHTML = css;
  head.appendChild(style);
}

addGlobalStyle(`
  #ctl{
  position: absolute;
  margin: auto;
  top: 0px;
  left: 0px;
  right: 0px;
  bottom: 0px;
  height: 80vh;
  width: 100vw;
  }
  .hideCursor{
  cursor: none !important;
  }
`);

function video_ctl(v){
  if(v.paused){
    v.play();
  }else{
    v.pause();
  }
}

var video_tag;
function mask_div(){
  video_tag = document.getElementsByTagName("video")[0];
  if(document.getElementById("ctl") == undefined){
    var div = document.createElement("div");
    div.id = "ctl";
    div.addEventListener("click", function(){video_ctl(video_tag)}, false);
    //カーソル消し
    var timer;
    div.addEventListener("mousemove", function(){
      div.className = "";
      clearTimeout(timer);
      timer = setTimeout(function() {
        div.className = "hideCursor";
      }, 1000);
    });
    var layered = document.getElementsByTagName("div")[2];
    layered.appendChild(div);
  }
  console.log("PPOS: loaded");
}

console.log("PPOS: activated");
var target = document.getElementById("app");
var observer = new MutationObserver(function(mutations){
    if(mutations[0].target.nodeName == "VIDEO"){mask_div();};
});
var options = {
  attributes: true,
  attributeFilter: ["src"],
  subtree: true
};
observer.observe(target, options);

console.logなど

起動しているかどうかの確認。αテストでは各所に散りばめてユーザースクリプトの処理がどのタイミングで行われるかを確認していました。htmlを読み込んだあと動的にvideoタグが生成されるようなので、何か工夫をしないとvideoタグを引っ張ってくるコードがエラーを吐きます。

Ovserver

前述の工夫というのがこれ。代案にスクリプト読み込んだ数秒後に開始するというタイマー処理も考えたが、廃止。理由は、ページ遷移時にスクリプトが再び読み込まれるということがないので、videoタグの参照先の変化を監視して動かそうという発想。

main

概要

手を加えていない時の最上位レイヤー(件のdiv)と同じ階層に新しくdivを付け加える。cssでabsoluteにしておけば,同じ階層だと後ろの行にあるdivが上にマスクされる.そこにonclickイベントを付けて再生制御.

DOS属性操作

タグの属性にアクセスする方法はいろいろあるようだけれど、
div.id = ‘abc’
のようにインスタンス変数的にアクセスする方法がわかりやすくて短いと思う(javascriptだとオプションと呼ぶらしい?)。onclick属性もそのようにアクセスできるけれど、引数を取る関数をonclickにするときとか、無名関数で複数行の処理をするときどうすれば良いか不明なのでaddEventlistenerで対応。つまり
div.addEventListener("click", function(){video_ctl(video_tag)}, false)
でなく
div.onclick = video_ctl
みたいな感じでも書けるということ。video_ctlの引数をグローバル変数にしたらこれでも動く.
あと、動画視聴ページに移行して再生が始められるまでにvideoタグがコロコロ変わるみたいで、その度に前述の監視が発火する。なのでif文で個数制御しておかないと大量のdivがマスクされることになる。

Timer

βテストをしてくれた母からの要望で書き加えた。これらの記述をすることで視聴中マウスカーソルが消えて、邪魔をしなくなる。

video_ctl

videoタグに対するメソッドはいろいろあって、この.pausedは一時停止しているときTrue、再生中はfalseを返してくれる。それでif分岐させてplay,pauseさせるのがこの関数。

おわりに

Unextユーザーは使うと便利だと,思う!配布先はこちら

参考

[1]JavaScriptでclass属性値を取得、変更する方法 https://lab.syncer.jp/Web/JavaScript/Snippet/76/
[2]Twitterから「いいね」を消し去るChrome拡張を作る - Qiita https://qiita.com/hal1437/items/59d7a55124027d2ff492
[3]z-index の値を無視して背面要素を操作可能にするCSS - Qiita https://qiita.com/shouchida/items/83c48c7423ea0eb617b8
[4]position:relativeとposition:absoluteで画像や文字を重ねてみよう https://naifix.com/relative-absolute/
[5]JavaScriptでのグローバル変数の宣言方法 | UX MILK https://uxmilk.jp/11598
[6]【DOM基礎】ノードの取得/属性の取得・設定 - Qiita https://qiita.com/KDE_SPACE/items/e21bb31dd4d9c162c4a6
[7]ライブラリを使わない素のJavaScriptでDOM操作 - Qiita https://qiita.com/kouh/items/dfc14d25ccb4e50afe89
[8]videoタグの動画埋め込み時に、画面クリックで再生、ポーズを設定する方法 - Qiita https://qiita.com/ryo2132/items/bac787725c983d0e3f4b
[9]How To Edit CSS within TamperMonkey (Edit Sites CSS) https://sinister.ly/Thread-Tutorial-How-To-Edit-CSS-within-TamperMonkey-Edit-Sites-CSS
[10]MutationObserver - †MASAYOSHI†のオンラインメモ帳 https://masayoshi-9a7ee.hatenablog.com/entry/20150627/1435372089
[11]

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした