動画サムネイルのライトボックス表示 

「GYAO!」サイトの動画コンテンツ数は大変に多く、サイトの半分以上の機能は、このデータベースをユーザーが利用し易くする事に費やされています。 検索だけでなく、色々なリストアップを使って、ユーザーに合ったコンテンツを探せる様に工夫されているわけです。

 

ただ、リストページの動画サムネイルが小さく、画像上のタイトル等の文字が読めない事が気になっていました。 その動画ページを開かないとおうよその内容が判らない時は、とても不便に感じます。

 

そこで最初は、CSSでサムネイルをフォバーで拡大するコードを作りましたが、余り良い結果が得られず、これはスクリプトが必要と判断しました。「Gyao! Comfy」は便利で簡単なツールですが、これにアメブロ用の「Ameblo Lightbox JS」のコードを移植する事にしました。

 

 

制作過程 

最低限の拡大機能があれば充分なので、あえて「Lightbox JS」の初期バージョンのコードを移植元に利用しました。

 

最も問題になったのは、「選択した画像の取得」の方法です。 コンテンツは大量で、ページを開いた後もスクロール操作で次々と追加され、メインのリストページでは最終的に数百のサムネイルが並びます。 この表示方式では、ページ上の画像を全取得してから画像を選択する「Lightbox JS」のコードは上手く働きません。

 

そこで、「マウスポイントした位置の要素を取得する」コードに変更しました。(ver. 0.4  204行)

 

document.addEventListener('contextmenu', function(event){
    event.preventDefault();
    let elm=document.elementFromPoint(event.clientX, event.clientY);
    let link_elm=elm.closest('a'); });

 

上はコードの要点だけですが、「右Click」した位置の要素「elm」を取得して、その要素にセットされたリンク「link_elm」(a要素)を取得するコードです。

 

 

サムネイル画像は軽量化されている 

現代のページデザインでは当然の事ですが、サムネイル画像はデータ量を減らすために軽量化されています。 これをCSSで拡大しても精細さに欠けますが、サムネイル画像は、多くの場合により精細な画像を変換して表示しているので、JavaScriptを使うと元画像の方を拡大表示できます。

 

 

 

動画サムネイル拡大の操作 

「GYAO!」サイトのほぼ全てのページの動画サムネイルに対応していますが、リストに並んだサムネイルを「右Click」すると、暗転拡大表示になります。

 

 

暗転拡大画面の任意の場所を「左Click」すると、元のリスト表示の画面に戻れます。 その間、スクロール位置は元の位置のままで、動画を探す操作を妨げません。

 

 

画面の上部 15%にポインターに乗せると「🎦 Movie Page」ボタンを表示します。 これは、選択したサムネイルの動画ページへのリンクです。 ボタンを「左Click」する事で、元のサムネイルをクリックしたのと同様に、動画ページが開きます。

(ライトボックスを閉じて、元のサムネイルをクリックしても同じ事ですが)

 

 

 

「Gyao! Comfy」の他の操作について 

「Gyao! Comfy」を常駐した状態で「動画ページ」を開くと、「動画再生開始」と同時に全画面表示になるなど、動画鑑賞上での操作が少し便利になります。 これは前ページの「操作マニュアル」に纏めているので参照ください。

 

 

 

 

 「Gyao! Comfy」を利用するには

このツールは Chrome / Edge / Firefox版の拡張機能「Tampermonkey」上で動作します。 以下に、このツールの導入手順を簡単に説明します。

 

❶「Tampermonkey」を導入します

◎ 使用しているブラウザに拡張機能「Tampermonkey」を導入する事が必要です。

既に「Tampermonkey」を導入している場合は、この手順 ❶ は不要です。 

拡張機能の導入については、以下のページに簡単な説明があるので参照ください。

 

 

❷「Tampermonkey」にスクリプトを登録します

◎「Tampermonkey」の「」マークの「新規スクリプト」タブを開きます。

 

 

 

◎「新規スクリプト」には、最初からテンプレートが記入されています。 これは全て削除して、完全に空白の編集枠に 下のコードをコピー&ペーストします。

 

〔コピー方法〕 軽量シンプルなツール「PreBox Button   」を使うと

  コード枠内を「Ctrl+左Click」➔「Copy code 」を「左Click」

  の操作で、掲載コードのコピーが可能になります。

 

◎ 最後に「ファイル」メニューの「保存」を押すと、ツールが使用可能になります。

 

 

〔 Gyao! Comfy 〕 ver. 0.4

 

// ==UserScript==
// @name         Gyao! Comfy
// @namespace    http://tampermonkey.net/
// @version      0.4
// @description   Gyao! 動画の「▶」のクリックで全画面表示
// @author       You
// @match        https://gyao.yahoo.co.jp/*
// @run-at document-start
// @grant        none
// ==/UserScript==


let retry=0;
let interval=setInterval(wait_target, 1);
function wait_target(){
    retry++;
    if(retry>100){ // リトライ制限 100回 0.1secまで
        clearInterval(interval); }
    let target=document.body; // 監視 target
    if(target){
        clearInterval(interval);
        style_in(); }}


function style_in(){

    let css1=
        '<style id="GC1" type="text/css">'+
        '/* GYAO動画のフル画面表示 ver. 202203.08.01 */'+
        ':root { --back: #91b4bf; --hove: #b9cfd6; }'+
        'html, body { background: var(--back); }'+
        '.button-favorite { opacity: .6; }'+
        '.button-favorite:hover { opacity: .8; }'+
        '.button-favorite .button-favorite-text { color: #000; }'+
        '.navigation-header-searchbar_searchSuggestResult__tU9rX, '+
        '.search-suggest-result { background-color: #d2dee3 !important; }'+
        '.arrow-button_arrowButton__aMtur:focus, '+
        '.arrow-button_arrowButton__aMtur { box-shadow: inset 0 0 0 4px #fff; }'+
        '.button-arrow:hover { box-shadow: 0 0 0 3px #fff; }'+
        '.schedule-list-item { padding: 0 6px; }'+
        '.schedule-list-item:hover { background: var(--hove); }'+
        '.schedule-list-item-sub-text { color: #000 !important; }'+
        '.schedule-list-container h3 { border-top: 1px solid #f0f0f0; }'+
        '.schedule-list .schedule-list-row-item:not(:last-child) { padding-right: 0; }'+
        '.schedule-list .schedule-list-row-item { border: none !important; }'+
        '.schedule-list .schedule-list-row-item h3, .schedule-list .schedule-list-row-item ul { '+
        'border-left: 1px solid #f0f0f0; border-right: 1px solid #f0f0f0; }'+
        '.program-list .program-list-more-link { margin-top: 30px; }'+
        '.more-link .more-link-text { color: #000; outline: 1px solid #eee; }'+
        '.more-link .more-link-text:active, .more-link .more-link-text:hover { '+
        'color: #fff; background-color: rgb(60 125 150 / 50%); }'+
        '.breadcrumb .breadcrumb-list-item-link, '+
        '.breadcrumb .breadcrumb-list-item:last-child .breadcrumb-list-item-link { color: #000; }'+
        '.breadcrumb_item__KOyoB * { color: #000 !important; }'+
        '.ad.ad-yads { display: none !important; }'+
        '.overlay-ad_ad__grVga { display: none !important; }'+
        '.timeline-ad_timelineAd__zM3OV { display: none !important; }'+
        '.image-lazy { background-color: #90aeb7; }'+
        'html::-webkit-scrollbar { width: 16px; }'+
        'html::-webkit-scrollbar-thumb { '+
        'background: #000; border: 1px solid var(--back); border-right: none; }'+
        'html::-webkit-scrollbar-track { background: transparent; }'+
        'html { scrollbar-color: #000 transparent; }'+
        'html { overflow: overlay; overflow-x: hidden; }</style>';

    if(!document.querySelector('#GC1')){
        document.documentElement.insertAdjacentHTML('beforeend', css1); }



    let path=document.location.pathname;
    if(path.match(/^\/ranking|^\/arrivals|^\/titles|^\/search|^\/schedule/)){

        let css2=
            '<style id="GC2" type="text/css">'+
            '/* 共通設定 */'+
            '.tab .tab-title > span { color: #000; }'+
            '.tab .tab-title.is-active { background: none; }'+
            '.tab .tab-title:active > span, .tab .tab-title:focus > span, '+
            '.tab .tab-title:hover > span { color: #000; }'+
            '.option-selector .option-selector-item > label { color: #000; }'+
            '.option-selector .option-selector-item > input:hover + label { color: #000; }'+
            '.program-list .program-list-item-title { color: #000; }'+
            '.program-list .content-label { color: #000; }'+
            '.program-list .program-list-item-sub-text { color: #000; }'+
            '.item-list .item-list-more-link { margin-top: 30px; }'+
            'html::-webkit-scrollbar-thumb { background: rgba(0, 0, 0, .2); }'+
            'html { scrollbar-color: rgba(0, 0, 0, .2) transparent; }</style>';

        if(!document.querySelector('#GC2')){
            document.documentElement.insertAdjacentHTML('beforeend', css2); }}



    if(path.match(/^\/p\/|^\/player\/|^\/episode\/|^\/title\//)){

        let css3=
            '<style id="GC3" type="text/css">'+
            '/* 個別の動画ページ 基本表示 */'+
            '.video-player.is-pip .video-player-titles { background-color: #223e4c; }'+
            '.video-player.is-pip .video-player-titles p { color: #ccc; }'+
            '.video-player.is-pip .video-player-titles:after { content: "▲"; '+
            'position: fixed; right: 20px; bottom: 15px; font: normal 32px/44px Meiryo; '+
            'text-indent: 6px; color: #fff; display: block; height: 50px; width: 50px; '+
            'border: 3px solid #fff; border-radius: 50%; }'+
            '.video-information .datetime { color: #000; }'+
            '.video-descriptions .video-description-main, '+
            '.program-descriptions .program-description-main { color: #000; }'+
            '.video-descriptions .content-text, .program-descriptions .content-text { color: #000; }'+
            '.container-clipper .container-clipper-content::after { '+
            'background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #b9cfd6); height: 50px; }'+
            '.video-list-more { background: var(--hove); }'+
            '.item-tile .item-tile-item-details { background: none; }'+
            '.item-tile-item-link:hover { background: var(--hove); }'+
            '.button.type-primary-white { background: var(--hove); }'+
            '.button.type-primary-white:hover { background: #c2edfb; }'+
            '.button.type-secondary { background: var(--hove); }'+
            '.button.type-secondary:hover { background: #c2edfb; }'+
            '.review-list-item-header-post-info .datetime { color: #000; }'+
            '.review-list .review-list-item-content-text { color: #000; }'+
            '.review-list-item-content-interstitial { color: #000 !important; background: var(--hove); }'+
            '.review-list-more { background: var(--hove); }'+
            '.video-list .video-list-item { padding: 0 4px; }'+
            '.video-list .video-list-item:hover { background-color: var(--hove); }'+
            '.video-list .video-list-item.is-current { background-color: var(--hove); }'+
            '.video-list .video-list-item-titles time { color: #000; }'+
            '.video-list .video-list-item-sub-text { color: #000; }'+
            '.section-upsell-item { padding: 0 4px; }'+
            '.ad-banner.ad.section { display: none; }'+
            '.to-app-banner.to-app-banner-footer, .footer-aside.footer-container { display: none; }'+
            '.vjs-gyao .vjs-head-bar .vjs-head-title { font-size: 1em; }'+
            '.vjs-gyao .vjs-control-bar .vjs-play-progress { background-color: #29b6f6; }'+
            'html::-webkit-scrollbar { width: 0px; }'+
            'html { scrollbar-width: none; }</style>';

        if(!document.querySelector('#GC3')){
            document.documentElement.insertAdjacentHTML('beforeend', css3); }}



    if(path.match(/^\/specials\/|^\/special\//)){

        let css6=
            '<style id="GC6" type="text/css">'+
            '/* 特設ページ */'+
            'body { font-family: "メイリオ", Meiryo, sans-serif !important; }'+
            '#cnt p, #cnt h3 { color: #fff !important; }</style>';

        if(!document.querySelector('#GC6')){
            document.documentElement.insertAdjacentHTML('beforeend', css6); }}

} // stylein()




window.addEventListener("load", function(){
    wider();
    catch_click(); });




function wider(){ // 動画PLAYで自動的に全画面表示にする
    //動作確認用のメニューボタンのアウトライン表示
    let lamp=document.querySelector('.header-menu-button');
    if(lamp){
        lamp.style.outlineOffset='-8px';
        lamp.style.outline='auto red';
        setTimeout(()=>{
            lamp.style.outline='none';
        }, 2000); }


    let play_button=document.querySelector('.vjs-big-play-button');
    let full_cont=document.querySelector('.vjs-gyao .vjs-fullscreen-control');
    if(play_button && full_cont){
        play_button.onclick=function(event){
            if(!event.ctrlKey && !event.shiftKey){
                full_cont.click(); }}


        document.onkeydown=function(event){
            if(event.ctrlKey || event.shiftKey){
                play_button.style.filter='hue-rotate(-135deg)'; }}


        document.onkeyup=function(event){
            play_button.style.filter='';
            if((event.ctrlKey && event.keyCode==13) ||
               (event.shiftKey && event.keyCode==13)){
                full_cont.click(); }}}

} // wider()




function catch_click(){ // 動画のサムネイルの暗転拡大表示
    let html_=document.querySelector('html');

    box_env();

    document.addEventListener('contextmenu', function(event){
        if(!event.shiftKey && !event.ctrlKey){
            event.preventDefault();
            let elem=document.elementFromPoint(event.clientX, event.clientY);
            let link_elem=elem.closest('a');

            if(link_elem){
                set_link(link_elem);
                set_img(link_elem);
                close(); }}});


    function box_env(){
        let lightbox=
            '<div id="lightbox">'+
            '<div id="photo_sw"><a id="photo_link">🎦 Movie Page</a></div>'+
            '<img id="box_img">'+
            '<style>'+
            '@keyframes fadeIn { 0% {opacity: 0} 100% {opacity: 1}} '+
            '.fin { animation: fadeIn .5s ease 0s 1 normal; animation-fill-mode: both; } '+
            '@keyframes fadeOut { 0% {opacity: 1} 100% {opacity: 0}} '+
            '.fout { animation: fadeOut .2s ease 0s 1 normal; animation-fill-mode: both; } '+
            '#lightbox { position: fixed; top: 0; left: 0; z-index: 3000; visibility: hidden; '+
            'background: black; width: 100vw; height: 100vh; text-align: center; } '+
            '#photo_sw { position: absolute; width: 100%; height: 15%; } '+
            '#photo_sw:hover #photo_link { opacity: 1; } '+
            '#photo_link { position: absolute; top: 20px; left: 30px; opacity: 0; '+
            'font: bold 21px Meiryo; padding: 4px 12px 2px 10px; background: #fff; '+
            'color: #000; border: 2px solid #000; border-radius: 6px; cursor: pointer; } '+
            '#box_img { width: 100vw; height: 100vh; padding: 2vh 2vw; object-fit: contain; } '+
            '</style></div>';

        if(!document.querySelector('#lightbox')){
            document.body.insertAdjacentHTML('beforeend', lightbox); }}


    function set_link(target){
        let photo_link=document.querySelector('#photo_link');
        if(photo_link){
            let url=target.getAttribute('href');
            if(url){
                photo_link.setAttribute('href', url); }

            photo_link.onclick=function(event){
                event.stopImmediatePropagation(); }}}


    function set_img(target){
        let lightbox=document.querySelector('#lightbox');
        let box_img=lightbox.querySelector('#box_img');
        let img=target.querySelector('img');
        if(lightbox && box_img && img){
            let img_url=img.getAttribute('src').replace(/\?.*$/,"");
            if(img_url){
                box_img.src=img_url;
                html_.style.overflow='hidden';
                lightbox.style.visibility='visible';
                lightbox.classList.remove('fout');
                lightbox.classList.add('fin'); }}}


    function close(){
        let html_=document.querySelector('html');
        let lightbox=document.querySelector('#lightbox');
        let box_img=lightbox.querySelector('#box_img');
        if(lightbox){
            lightbox.onclick=function(event){
                event.preventDefault();
                html_.style.overflow='inherit';
                lightbox.classList.remove('fin');
                lightbox.classList.add('fout');
                setTimeout(()=>{
                    lightbox.style.visibility='hidden';
                    box_img.src='';
                }, 200); }}}

} // catch_click()