ETH官方钱包

前往
大廳
主題

迷你懸浮視窗腳本

Jason | 2024-12-17 23:57:47 | 巴幣 0 | 人氣 104

// ==UserScript==
// @name         Youtube 迷你懸浮視窗
// @namespace    http://tampermonkey.net/
// @version      2024-03-29
// @description  try to take over the world!
// @author       You
// @match        https://www.youtube.com/*
// @grant        GM_addStyle
// ==/UserScript==

//●目前問題
//※在迷你懸浮視窗移動(dòng)的過程中,如果按下右鍵(此時(shí)鼠標(biāo)正在迷你懸浮視窗上)
//會(huì)有即使你鬆開左鍵迷你懸浮視窗還是會(huì)黏在你鼠標(biāo)上的bug
//如果將迷你懸浮視窗拖曳到視窗外放開左鍵也會(huì)有這個(gè)bug

//阻止影片加速的功能,並不是完全阻止影片加速,中間還是會(huì)有類似一幀的播放

//懸浮視窗大小是設(shè)定鎖死的 320px * 180px,所以遇到其他大小的影片比例(EX:直式短影音)會(huì)看不到完整影片
//若要改善可能整個(gè)4個(gè)拖曳區(qū)塊大小、播放/暫停鍵位置、懸浮視窗關(guān)閉按鈕的位置都要重寫

//(已解決)如果是在影片介面(網(wǎng)址含有youtube.com/watch?v=)重整
//當(dāng)下由於抓不到影片元素腳本就被執(zhí)行的關(guān)係,整個(gè)懸浮視窗除了CSS的部分其他都無法套用
//點(diǎn)擊進(jìn)去其他影片就可以恢復(fù)

//有時(shí)候影片播放狀態(tài)跟暫停/播放鍵的狀態(tài)還是會(huì)不同(EX:影片正在播放可以暫停/播放鍵顯示的是三角形)

//是否顯示進(jìn)度條
const DisplayProgressBar = true;

(function() {
    GM_addStyle(`
        .mini-close {
            float: right;
            position: relative;
            bottom: 382px;
            right: 7px;
            fill: #fff;
            width: 26px;
            height: 26px;
            opacity: 0;
            z-index: 200;
            /*cursor: pointer;*/
            transition: 0.2s;
        }
        .mini-state-play , .mini-state-pause {
            /*border: 1px #fff solid;*/
            position: relative;
            left: 100px;
            width: 119px;
            height: 104px;
            opacity: 0;
            transition: 0.2s;
        }
        #movie_player:not(.alike) .mini-state-play button svg path,
        #movie_player:not(.alike) .mini-state-pause button svg path {
            display: none;
        }
        #movie_player:not(.alike) .mini-state-play , #movie_player:not(.alike) .mini-state-pause {
            z-index: -1;
        }
        .mini-state-play {
            bottom: 145px;
        }
        .mini-state-pause {
            bottom: 251px;
            /*padding-left: 1px;*/
        }
        .drag {
            border: 0px #000 solid;
            /*cursor: move;*/
            position: relative;
            z-index: 100;
        }
        .drag-top {
            width: 100%;
            height: 40px;
        }
        .drag-left {
            width: 100px;
            height: 100px;
            float: left;
        }
        .drag-right {
            width: 100px;
            height: 100px;
            float: right;
        }
        .drag-bottom {
            width: 100%;
            height: 40px;
            margin-top: 100px
        }
        #movie_player.ytp-fullscreen {
            width: 100% ;
            height: 100% ;
            position: static;
        }
        #movie_player.alike:not(.ytp-fullscreen) {
            position: fixed;
            z-index: 1337;
            width: 320px ;
            height: 180px ;
            border-radius: 8px;
            box-shadow: 0px 0px 8px #000 !important;
            /*如果要回復(fù)以前預(yù)設(shè)的懸浮視窗位置,把下面的margin left top註解掉就好*/
            margin: 0 !important;
            left: 850px;
            top: 400px;
        }
        #movie_player.alike:not(.ytp-fullscreen) .ytp-bezel-text-hide ,
        #movie_player.alike:not(.ytp-fullscreen) .ytp-spinner ,
        #movie_player.alike:not(.ytp-fullscreen) .ytp-overlay .ytp-speedmaster-has-icon,
        #movie_player.alike:not(.ytp-fullscreen) .ytp-gradient-bottom ,
        #movie_player.alike:not(.ytp-fullscreen) .html5-endscreen ,
        #movie_player.alike:not(.ytp-fullscreen) .ytp-ce-element{
            display: none !important;
        }
        #columns #movie_player.alike > .ytp-chrome-bottom {
            display: none;
        }
        .mini-progress-bar .ytp-chapter-hover-container {
            width: 320px !important;
        }
        .mini-progress-bar {
            opacity: 0;
            /*transition: 0.1s;*/
            top: 176px;
            pointer-events: none;
        }
        ytd-watch-flexy:not(.alikeSmall) #columns #movie_player.alike:not(.ytp-fullscreen) video,
        ytd-watch-flexy:not(.alikeSmall) #columns #movie_player.alike:not(.ytp-fullscreen) .html5-video-container {
            display: block;
            width: 100% !important;
            height: 100% !important;
            top: 0 !important;
            left: 0 !important;
        }
        /*CC字幕*/
        #movie_player.alike:not(.ytp-fullscreen) #ytp-caption-window-container .caption-window .captions-text .caption-visual-line .ytp-caption-segment {
            font-size: 14.5px !important;
        }
        #movie_player.alike:not(.ytp-fullscreen) .caption-window.ytp-caption-window-bottom {
            margin-bottom: 4px !important;
            pointer-events: none;
        }
    `);
    let playerDocked = false;
    function activate() {
        if (!playerDocked) {
          $("#movie_player").addClass("alike");
          window.dispatchEvent(new Event('resize'));
          playerDocked = true;
        }
    }
    function deactivate() {
        if (playerDocked) {
          $("#movie_player").removeClass("alike");
          window.dispatchEvent(new Event('resize'));
          playerDocked = false;
        }
    }
    function scrolling() {
        let limiter = $("#player-container #ytd-player");
        let top_of_element = $(limiter).offset().top;
        let bottom_of_element = $(limiter).offset().top + $(limiter).outerHeight();
        let bottom_of_screen = $(window).scrollTop() + $(window).innerHeight();
        let top_of_screen = $(window).scrollTop();
        if ((bottom_of_screen > top_of_element) && (top_of_screen < bottom_of_element)) {
          //如果影片可視(迷你視窗關(guān)閉)
          deactivate();
          $('#movie_player').css('right','');
          $('#movie_player').css('left','');
          $('#movie_player').css('top','');
          $('#movie_player').css('bottom','');
        } else {
          //如果影片不可視(迷你視窗開啟)
          activate();
        }
    }
    //阻止長按加速功能
    function preventLongPressAcceleration() {
        let timeStart, timeEnd , time;
        $('.mini-state-pause , .mini-state-play , .drag , .mini-close').each((index) => {
            $('.mini-state-pause , .mini-state-play , .drag , .mini-close')[index].onmousedown = (e) => {
                if($('#movie_player.alike')[0]) {
                    timeStart = new Date().getTime();
                    time = setInterval(() => {
                        timeEnd = new Date().getTime();
                        if(timeEnd - timeStart > 560) {
                            clearInterval(time);
                            $('.html5-video-container video')[0].playbackRate = $('.ytp-bezel[aria-label = "暫停"]')[0]||$('.ytp-bezel[aria-label="停止即時(shí)播放"]')[0] ? 0 : 1;
                        }
                    }, 10);
                }
            }
        });
        $('.mini-state-pause , .mini-state-play , .drag , .mini-close').each((index) => {
            $('.mini-state-pause , .mini-state-play , .drag , .mini-close')[index].onmouseup = (e) => {
                if($('#movie_player.alike')[0]) {
                   clearInterval(time);
                   $('.html5-video-container video')[0].playbackRate = 1;
                }
            }
        });
    }
    //確保找到影片元素再執(zhí)行
    function findMoviePlayer() {
        return new Promise((resolve, reject) => {
            const checkPlayer = () => {
                if ($('#movie_player')[0] === undefined) {
                    //console.log('抓不到');
                    setTimeout(checkPlayer, 100);
                }
                else {
                    resolve($('#movie_player')[0]);
                }
            }
            checkPlayer();
        });
    }
    //主要拖曳事件函數(shù)  參考來自:https://zh.javascript.info/mouse-drag-and-drop
    function drag(miniVideo, flag) {
        //let miniVideo = $('#movie_player')[0];
        //console.log(miniVideo);
        miniVideo.onmousedown = (e) => {
            //如果現(xiàn)在是一般頁面(迷你懸浮視窗沒有出現(xiàn)),則不給拖曳
            if(!$('#movie_player.alike:not(.ytp-fullscreen)')[0]) return
            let mouseCoordinatesX = e.pageX - $('#movie_player').offset().left;
            let mouseCoordinatesY = e.pageY - $('#movie_player').offset().top;
            //console.log(e.pageX - $('#movie_player').offset().left,e.pageY - $('#movie_player').offset().top);
            //如果在播放按鈕上,則不給拖曳
            if(100 < mouseCoordinatesX && mouseCoordinatesX < 200 && 39 < mouseCoordinatesY && mouseCoordinatesY < 139) {
                //console.log('現(xiàn)在在播放按鈕上');
                //終止冒泡,取消滑鼠在播放按鈕上的拖曳效果所造成的暫停/播放
                e.stopPropagation();
                return
            }

            let shiftX = e.clientX - miniVideo.getBoundingClientRect().left;
            let shiftY = e.clientY - miniVideo.getBoundingClientRect().top;
            function move(clientX , clientY) {
                miniVideo.style.left = clientX - shiftX + 'px';
                miniVideo.style.top = clientY - shiftY + 'px';
            }
            move(e.clientX, e.clientY);

            function onMouseMove(e) {
                move(e.clientX, e.clientY);
            }

            document.addEventListener('mousemove', onMouseMove);

            miniVideo.onmouseup = () => {
                document.removeEventListener('mousemove', onMouseMove);
                miniVideo.onmouseup = null;
            }
        }
        miniVideo.ondragstart = () => {
            return false;
        }
    };
    function addNode() {
         $('.html5-video-container').append($(`<div class='drag drag-top'></div>`));
         $('.html5-video-container').append($(`<div class='drag drag-left'></div>`));
         $('.html5-video-container').append($(`<div class='drag drag-right'></div>`));
         $('.html5-video-container').append($(`<div class='drag drag-bottom'></div>`));
         $('.html5-video-container').append($(`<div class='mini-state-play'></div>`));
         $('.html5-video-container').append($(`<div class='mini-state-pause'></div>`));
         $('.html5-video-container').append($(`<div class='mini-close'></div>`));
         //影片暫停時(shí)的播放標(biāo)誌(三角形)
         $('.mini-state-pause').append($(`<button class="ytp-play-button ytp-button" aria-keyshortcuts="k" data-title-no-tooltip="播放" aria-label="播放鍵盤快速鍵k"><svg height="100%" version="1.1" viewBox="0 0 36 36" width="100%"><use class="ytp-svg-shadow" xlink:href="#ytp-id-43"></use><path class="ytp-svg-fill" d="M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z" id="ytp-id-43"></path></svg></button>`));
         //影片播放時(shí)的播放標(biāo)誌(雙長方形)
         $('.mini-state-play').append($(`<button class="ytp-play-button ytp-button" aria-keyshortcuts="k" data-title-no-tooltip="暫停" aria-label="暫停鍵盤快速鍵k"><svg height="100%" version="1.1" viewBox="0 0 36 36" width="100%"><use class="ytp-svg-shadow" xlink:href="#ytp-id-73"></use><path class="ytp-svg-fill" d="M 12,26 16,26 16,10 12,10 z M 21,26 25,26 25,10 21,10 z" id="ytp-id-73"></path></svg></button>`));
         //增加右上角關(guān)閉迷你懸浮視窗的按鈕
         $('.mini-close').append($(`<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" data-pointer="none" viewBox="0 0 16 16"><path d="m8 6.939 3.182-3.182a.75.75 0 1 1 1.061 1.061L9.061 8l3.182 3.182a.75.75 0 1 1-1.061 1.061L8 9.061l-3.182 3.182a.75.75 0 1 1-1.061-1.061L6.939 8 3.757 4.818a.75.75 0 1 1 1.061-1.061L8 6.939z"></path></svg>`));
    }
    function miniProgressBar() {
        if($('#movie_player.alike:not(.ytp-fullscreen)')[0]) {
            if(!$('.mini-progress-bar')[0]) {
                $('#movie_player').append($('.ytp-progress-bar-container'));
                $('.ytp-progress-bar-container').addClass('mini-progress-bar');
                $('.mini-progress-bar').css('opacity', '0');
                $('.ytp-progress-bar-container').css('display', 'block');
                //console.log('已增加');
            }
        }
        else if($('#movie_player:not(.alike)')[0]||$('#movie_player.ytp-fullscreen')[0]) {
            if($('.mini-progress-bar')[0]) {
                $('.ytp-chrome-bottom').append($('.ytp-progress-bar-container'));
                $('.mini-progress-bar').css('opacity', '1');
                $('.ytp-progress-bar-container').removeClass('mini-progress-bar');
                //console.log('已還原');
            }
        }
    }
    async function handleUIActions(nowUrl) {
        //暫停時(shí)點(diǎn)擊其他影片進(jìn)去後會(huì)自動(dòng)播放,所以將標(biāo)籤內(nèi)容改正回來,改為.ytp-bezel[aria-label = "播放"]
        await findMoviePlayer();
        if(nowUrl!==window.location.href) {
            $('.ytp-bezel[aria-label = "暫停"] , .ytp-bezel[aria-label="停止即時(shí)播放"]').attr('aria-label', '播放');
            miniProgressBar();
         }
        /*$('.drag , .mini-close').mouseover((e) => {
            if($('#movie_player.alike:not(.ytp-fullscreen)')[0]) {
                //終止冒泡
                $('.drag').css('cursor', 'move');
                $('.mini-close').css('cursor', 'pointer');
                }
        });*/
        //在迷你懸浮視窗上的「可移動(dòng)區(qū)域」、「關(guān)閉按鈕」上,封鎖點(diǎn)擊滑鼠左鍵造成暫停的效果
        $('.drag , .mini-close').click((e) => {
            if($('#movie_player.alike:not(.ytp-fullscreen)')[0]) {
                //終止冒泡
                e.stopPropagation();
            }
        });
        //滑鼠移動(dòng)到迷你懸浮視窗上的「可移動(dòng)區(qū)域」、「關(guān)閉按鈕」時(shí),改變滑鼠樣式
        $('.drag , .mini-close').mouseover((e) => {
            if($('#movie_player.alike:not(.ytp-fullscreen)')[0]) {
                $('.drag').css('cursor', 'move');
                $('.mini-close').css('cursor', 'pointer');
            }
        });

        //滑鼠移上去時(shí)顯示暫停/播放標(biāo)誌
        $('.mini-state-pause , .mini-state-play , .drag , .mini-close').mouseover((e) => {
            if($('#movie_player.alike')[0]) {
                //當(dāng)滑鼠移上去時(shí),如果目前是暫停狀態(tài),表示點(diǎn)擊後會(huì)播放,所以顯示播放圖示,隱藏暫停圖示
                if($('.ytp-bezel[aria-label = "暫停"]')[0]||$('.ytp-bezel[aria-label="停止即時(shí)播放"]')[0]) {
                   $('.mini-state-pause').css('opacity', '0.9');
                   $('.mini-state-play').css('opacity', '0');
                }
                //當(dāng)滑鼠移上去時(shí),如果目前是播放狀態(tài),表示點(diǎn)擊後會(huì)暫停,所以顯示暫停圖示,隱藏播放圖示
                else {
                    $('.mini-state-pause').css('opacity', '0');
                    $('.mini-state-play').css('opacity', '0.9');
                }
                $('.mini-close , .mini-progress-bar').css('opacity', '0.9');
                $('.mini-progress-bar').css('opacity', '1');
                $('.mini-state-pause .ytp-button , .mini-state-play .ytp-button').css('cursor', 'pointer');
            }
            else {
                $('.mini-state-pause .ytp-button , .mini-state-play .ytp-button').css('cursor', 'default');
                $('.drag').css('cursor', 'default');
                $('.mini-close').css('cursor', 'default');
            }
        });
        $('.mini-state-pause , .drag , .mini-close').mouseout((e) => {
            $('.mini-state-pause , .mini-state-play , .mini-close , .mini-progress-bar').css('opacity', '0');
        });
        //點(diǎn)擊播放、暫停時(shí),更換標(biāo)誌
        $('.mini-state-pause').click((e) => {
            if($('#movie_player.alike')[0]) {
                //當(dāng)點(diǎn)擊時(shí),如果目前是暫停狀態(tài),表示點(diǎn)擊後會(huì)播放,所以顯示播放圖示,隱藏暫停圖示
                if($('.ytp-bezel[aria-label = "暫停"]')[0]||$('.ytp-bezel[aria-label="停止即時(shí)播放"]')[0]) {
                    $('.mini-state-pause').css('opacity', '0');
                    $('.mini-state-play').css('opacity', '0.9');
                    //這邊在檢查到$('.ytp-bezel[aria-label = "暫停"]')[0]後將其印出
                    //但結(jié)果是ytp-bezel[aria-label = "播放"],表示在按下按鈕的那刻還是暫停狀態(tài),之後就變到播放狀態(tài)了
                    //console.log($('.ytp-bezel[aria-label = "暫停"]')[0],'播放');
                }
                //當(dāng)點(diǎn)擊時(shí),如果目前是播放狀態(tài),表示點(diǎn)擊後會(huì)暫停,所以顯示暫停圖示,隱藏播放圖示
                else {
                    $('.mini-state-pause').css('opacity', '0.9');
                    $('.mini-state-play').css('opacity', '0');
                    //console.log($('.ytp-bezel[aria-label = "暫停"]')[0],'暫停');
                }
            }
            //e.stopPropagation();
        });

        //右上角關(guān)閉迷你懸浮視窗的按鈕功能實(shí)現(xiàn)
        $('.mini-close').click(() => {
            /*if(!$('#movie_player:not(.alike)')[0]) {
                $('#movie_player').hide();
            }*/
            $("#movie_player").removeClass("alike");
        });
    }
    async function Run() {
        let miniVideo = await findMoviePlayer();
        drag(miniVideo);
        addNode();
        preventLongPressAcceleration();
    }
    $(() => {
        window.addEventListener("yt-navigate-finish", () => {
            if (window.location.href.indexOf('youtube.com/watch?v=') > -1) {
                $("#movie_player").removeClass("alike");
                //scrolling();
                $(window).scroll(() => {
                    scrolling();
                });
                if(!$('.drag')[0]) {
                    //儲(chǔ)存目前網(wǎng)址,用來檢查有沒有切換頁面
                    var nowUrl = window.location.href;
                    Run();
                }
                handleUIActions(nowUrl);
                if(DisplayProgressBar) {
                    $(window).scroll(() => {
                        miniProgressBar();
                    });
                    $(window).keydown((e) => {
                        if(e.keyCode == 70) {
                            miniProgressBar();
                        }
                    });
                }
            }
            else {
                if($("#movie_player.alike")[0]) $("#movie_player").removeClass("alike");
                console.log('非影片介面');
                console.log($("#movie_player")[0]);
            }
        });
    });

})();

更多創(chuàng)作