Greasy Fork

Greasy Fork is available in English.

動畫瘋 - 截圖工具

在 動畫瘋 加入 截圖 的功能

目前为 2019-08-17 提交的版本,查看 最新版本

// ==UserScript==
// @name         動畫瘋 - 截圖工具
// @namespace    hbl917070
// @version      0.1
// @description  在 動畫瘋 加入 截圖 的功能
// @author       hbl917070(深海異音)
// @match        https://ani.gamer.com.tw/animeVideo.php?sn=*
// @grant        none
// ==/UserScript==



/**
 * 最後修改日期:
 * 2019/08/18
 * 
 * 說明:
 * 在 動畫瘋 加入 截圖 的功能
 * 
 * 作者小屋:
 * https://home.gamer.com.tw/homeindex.php?owner=hbl917070
 * 
 */


(function () {


    //要插入的html

    var s_html = `
    <div class="ct_div">

    <style>
        /*最外層的框*/
        .ct_div {
            background-color: #FFF;
            padding: 5px;
            padding-left: 11px;
        }

        /*「截圖」按鈕*/
        .but_ct {
            margin-top: 10px;
            padding: 3px 10px;
            border: 1px solid #00B4D8;
            color: #00B4D8;
            display: inline-block;
            text-align: center;
            line-height: 27px;
            font-size: 1.3em;
            margin-right: 10px;
        }

        .but_ct:hover {
            background-color: #00B4D8;
            border: 1px solid #00B4D8;
            color: #FFF;
            display: inline-block;

        }

        /*放每一個截圖的區域*/
        #ct_output {
            max-height: 500px;
            overflow: auto;
            margin-top: 10px;
        }

        /*每一個截圖項目*/
        .ct_item {
            margin-bottom: 10px;
            margin-right: 10px;
            border: 1px solid #d9d9d9;
            float: left;
            padding: 5px;
            white-space: nowrap;
        }

        .ct_img {
            max-width: 195px;
            max-height: 150px;
        }

        /*影片時間*/
        .ct_time {
            float: left;
            margin-top: 5px;
            font-size: 18px;
        }

        /*下載圖片*/
        .ct_download {
            float: right;
            display: block;
            width: 20px;
            height: 20px;
            background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjQzMy41cHgiIGhlaWdodD0iNDMzLjVweCIgdmlld0JveD0iMCAwIDQzMy41IDQzMy41IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA0MzMuNSA0MzMuNTsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQoJPg0KPGc+DQoJPGcgaWQ9ImZpbGUtZG93bmxvYWQiPg0KCQk8cGF0aCBkPSJNMzk1LjI1LDE1M2gtMTAyVjBoLTE1M3YxNTNoLTEwMmwxNzguNSwxNzguNUwzOTUuMjUsMTUzeiBNMzguMjUsMzgyLjV2NTFoMzU3di01MUgzOC4yNXoiLz4NCgk8L2c+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8L3N2Zz4NCg==);
            background-size: 90% 90%;
            background-position: center center;
            background-repeat: no-repeat;
            opacity: 0.2;
            margin-top: 3px;
        }

        .ct_download:hover {
            opacity: 1;
        }

        /*刪除圖片*/
        .ct_delete {
            float: right;
            display: block;
            width: 20px;
            height: 20px;
            background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQyN3B0IiB2aWV3Qm94PSItNDAgMCA0MjcgNDI3LjAwMTMxIiB3aWR0aD0iNDI3cHQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTIzMi4zOTg0MzggMTU0LjcwMzEyNWMtNS41MjM0MzggMC0xMCA0LjQ3NjU2My0xMCAxMHYxODljMCA1LjUxOTUzMSA0LjQ3NjU2MiAxMCAxMCAxMCA1LjUyMzQzNyAwIDEwLTQuNDgwNDY5IDEwLTEwdi0xODljMC01LjUyMzQzNy00LjQ3NjU2My0xMC0xMC0xMHptMCAwIi8+PHBhdGggZD0ibTExNC4zOTg0MzggMTU0LjcwMzEyNWMtNS41MjM0MzggMC0xMCA0LjQ3NjU2My0xMCAxMHYxODljMCA1LjUxOTUzMSA0LjQ3NjU2MiAxMCAxMCAxMCA1LjUyMzQzNyAwIDEwLTQuNDgwNDY5IDEwLTEwdi0xODljMC01LjUyMzQzNy00LjQ3NjU2My0xMC0xMC0xMHptMCAwIi8+PHBhdGggZD0ibTI4LjM5ODQzOCAxMjcuMTIxMDk0djI0Ni4zNzg5MDZjMCAxNC41NjI1IDUuMzM5ODQzIDI4LjIzODI4MSAxNC42Njc5NjggMzguMDUwNzgxIDkuMjg1MTU2IDkuODM5ODQ0IDIyLjIwNzAzMiAxNS40MjU3ODEgMzUuNzMwNDY5IDE1LjQ0OTIxOWgxODkuMjAzMTI1YzEzLjUyNzM0NC0uMDIzNDM4IDI2LjQ0OTIxOS01LjYwOTM3NSAzNS43MzA0NjktMTUuNDQ5MjE5IDkuMzI4MTI1LTkuODEyNSAxNC42Njc5NjktMjMuNDg4MjgxIDE0LjY2Nzk2OS0zOC4wNTA3ODF2LTI0Ni4zNzg5MDZjMTguNTQyOTY4LTQuOTIxODc1IDMwLjU1ODU5My0yMi44MzU5MzggMjguMDc4MTI0LTQxLjg2MzI4Mi0yLjQ4NDM3NC0xOS4wMjM0MzctMTguNjkxNDA2LTMzLjI1MzkwNi0zNy44Nzg5MDYtMzMuMjU3ODEyaC01MS4xOTkyMTh2LTEyLjVjLjA1ODU5My0xMC41MTE3MTktNC4wOTc2NTctMjAuNjA1NDY5LTExLjUzOTA2My0yOC4wMzEyNS03LjQ0MTQwNi03LjQyMTg3NS0xNy41NTA3ODEtMTEuNTU0Njg3NS0yOC4wNjI1LTExLjQ2ODc1aC04OC43OTY4NzVjLTEwLjUxMTcxOS0uMDg1OTM3NS0yMC42MjEwOTQgNC4wNDY4NzUtMjguMDYyNSAxMS40Njg3NS03LjQ0MTQwNiA3LjQyNTc4MS0xMS41OTc2NTYgMTcuNTE5NTMxLTExLjUzOTA2MiAyOC4wMzEyNXYxMi41aC01MS4xOTkyMTljLTE5LjE4NzUuMDAzOTA2LTM1LjM5NDUzMSAxNC4yMzQzNzUtMzcuODc4OTA3IDMzLjI1NzgxMi0yLjQ4MDQ2OCAxOS4wMjczNDQgOS41MzUxNTcgMzYuOTQxNDA3IDI4LjA3ODEyNiA0MS44NjMyODJ6bTIzOS42MDE1NjIgMjc5Ljg3ODkwNmgtMTg5LjIwMzEyNWMtMTcuMDk3NjU2IDAtMzAuMzk4NDM3LTE0LjY4NzUtMzAuMzk4NDM3LTMzLjV2LTI0NS41aDI1MHYyNDUuNWMwIDE4LjgxMjUtMTMuMzAwNzgyIDMzLjUtMzAuMzk4NDM4IDMzLjV6bS0xNTguNjAxNTYyLTM2Ny41Yy0uMDY2NDA3LTUuMjA3MDMxIDEuOTgwNDY4LTEwLjIxODc1IDUuNjc1NzgxLTEzLjg5NDUzMSAzLjY5MTQwNi0zLjY3NTc4MSA4LjcxNDg0My01LjY5NTMxMyAxMy45MjU3ODEtNS42MDU0NjloODguNzk2ODc1YzUuMjEwOTM3LS4wODk4NDQgMTAuMjM0Mzc1IDEuOTI5Njg4IDEzLjkyNTc4MSA1LjYwNTQ2OSAzLjY5NTMxMyAzLjY3MTg3NSA1Ljc0MjE4OCA4LjY4NzUgNS42NzU3ODIgMTMuODk0NTMxdjEyLjVoLTEyOHptLTcxLjE5OTIxOSAzMi41aDI3MC4zOTg0MzdjOS45NDE0MDYgMCAxOCA4LjA1ODU5NCAxOCAxOHMtOC4wNTg1OTQgMTgtMTggMThoLTI3MC4zOTg0MzdjLTkuOTQxNDA3IDAtMTgtOC4wNTg1OTQtMTgtMThzOC4wNTg1OTMtMTggMTgtMTh6bTAgMCIvPjxwYXRoIGQ9Im0xNzMuMzk4NDM4IDE1NC43MDMxMjVjLTUuNTIzNDM4IDAtMTAgNC40NzY1NjMtMTAgMTB2MTg5YzAgNS41MTk1MzEgNC40NzY1NjIgMTAgMTAgMTAgNS41MjM0MzcgMCAxMC00LjQ4MDQ2OSAxMC0xMHYtMTg5YzAtNS41MjM0MzctNC40NzY1NjMtMTAtMTAtMTB6bTAgMCIvPjwvc3ZnPg==);
            background-size: 90% 90%;
            background-position: center center;
            background-repeat: no-repeat;
            opacity: 0.2;
            margin-top: 3px;
            margin-right: 20px;
        }

        .ct_delete:hover {
            opacity: 1;
        }

        /*開啟圖片*/
        .ct_open {
            float: right;
            display: block;
            width: 20px;
            height: 20px;
            background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgNDUxIDQ1MSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDUxIDQ1MTsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGc+DQoJPHBhdGggZD0iTTQ0Ny4wNSw0MjhsLTEwOS42LTEwOS42YzI5LjQtMzMuOCw0Ny4yLTc3LjksNDcuMi0xMjYuMUMzODQuNjUsODYuMiwyOTguMzUsMCwxOTIuMzUsMEM4Ni4yNSwwLDAuMDUsODYuMywwLjA1LDE5Mi4zDQoJCXM4Ni4zLDE5Mi4zLDE5Mi4zLDE5Mi4zYzQ4LjIsMCw5Mi4zLTE3LjgsMTI2LjEtNDcuMkw0MjguMDUsNDQ3YzIuNiwyLjYsNi4xLDQsOS41LDRzNi45LTEuMyw5LjUtNA0KCQlDNDUyLjI1LDQ0MS44LDQ1Mi4yNSw0MzMuMiw0NDcuMDUsNDI4eiBNMjYuOTUsMTkyLjNjMC05MS4yLDc0LjItMTY1LjMsMTY1LjMtMTY1LjNjOTEuMiwwLDE2NS4zLDc0LjIsMTY1LjMsMTY1LjMNCgkJcy03NC4xLDE2NS40LTE2NS4zLDE2NS40QzEwMS4xNSwzNTcuNywyNi45NSwyODMuNSwyNi45NSwxOTIuM3oiLz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjwvc3ZnPg0K);
            background-size: 90% 90%;
            background-position: center center;
            background-repeat: no-repeat;
            opacity: 0.2;
            margin-top: 3px;
            margin-right: 20px;
        }

        .ct_open:hover {
            opacity: 1;
        }
    </style>


    <div class="but_ct" onclick="add_ct()">截圖</div>
    <span style="font-size:14px; color:rgb(100, 100, 100)">(截圖快速鍵 「F8」</span>


    <div id="ct_output"></div>

    <div id="temp_ct_item" style="display:none;">
        <div class="ct_item">

            <img class="ct_img" src="{{ct_img}}">
            <div>
                <div class="ct_time">{{ct_time}}</div>
                <a class="ct_download" download="{{ct_name}}" href="{{ct_img}}"></a>
                <a class="ct_open" href="{{ct_img}}" target="_blank"></a>
                <div class="ct_delete" onclick="ct_delete('{{nub}}')"></div>
            </div>

        </div>
    </div>
</div>

</div>
`;

    var dom_div = document.createElement('div');
    dom_div.innerHTML = s_html;

    //目前截圖的編號(用於刪除圖片)
    window.ct_nub = 1;

    //把截圖的按鈕,插入到標題上方
    var dom_player = document.getElementsByClassName('anime-title')[0];
    dom_player.parentNode.insertBefore(dom_div, dom_player);

    //繪製圖片用的 canvas
    var cc = document.createElement('canvas');
    document.body.append(cc);

    //截圖快速鍵
    document.body.addEventListener("keydown", function (e) {
        if (e.keyCode == 119) { //F8
            add_ct();
        }
    });


    /**
       * 影片截圖
       */
    function add_ct() {

        //取得影片目前的畫面
        var video = document.getElementById('ani_video_html5_api');
        cc.width = video.videoWidth;
        cc.height = video.videoHeight;
        cc.setAttribute('style', 'width:0px; height:0px;');
        cc.getContext('2d').drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
        let base64 = cc.toDataURL("image/jpeg", 0.95);

        let imgsrc = URL.createObjectURL(dataURItoBlob(base64));// Blob url
        let imgtime = document.querySelector('.vjs-current-time .vjs-current-time-display').innerHTML;//目前時間
        let imgname = document.querySelector('.anime_name h1').innerHTML + ' ' + imgtime.replace(/[:]/g, ':');//圖片檔名


        let dom_ct_item = document.createElement('div');
        dom_ct_item.setAttribute('class', 'ct_item ' + 'ct_nub_' + window.ct_nub);
        let shtml = `
                    <img class="ct_img" src="{{ct_img}}">
                    <div>
                        <div class="ct_time">{{ct_time}}</div>
                        <a class="ct_download" download="{{ct_name}}" href="{{ct_img}}"></a>
                        <a class="ct_open" href="{{ct_img}}" target="_blank"></a>
                        <div class="ct_delete" onclick="ct_delete('{{nub}}')"></div>
                    </div>
                    `;
        shtml = shtml.replace(/{{ct_img}}/g, imgsrc)
            .replace(/{{ct_time}}/g, imgtime)
            .replace(/{{ct_name}}/g, imgname)
            .replace(/{{nub}}/g, window.ct_nub);

        dom_ct_item.innerHTML = shtml;
        document.getElementById('ct_output').append(dom_ct_item);

        window.ct_nub += 1;
    }

    /**
     * 刪除圖片
     * @param nub 
     */
    function ct_delete(nub) {
        let child = document.querySelector('.ct_nub_' + nub);
        child.parentNode.removeChild(child);
    }


    /**
     * Blob object 轉 Blob url
     * @param dataURI 
     */
    function dataURItoBlob(dataURI) {
        // convert base64/URLEncoded data component to raw binary data held in a string
        var byteString;
        if (dataURI.split(',')[0].indexOf('base64') >= 0)
            byteString = atob(dataURI.split(',')[1]);
        else
            byteString = unescape(dataURI.split(',')[1]);

        // separate out the mime component
        var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

        // write the bytes of the string to a typed array
        var ia = new Uint8Array(byteString.length);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }

        return new Blob([ia], { type: mimeString });
    }

    window.add_ct = add_ct;
    window.ct_delete = ct_delete;
    window.dataURItoBlob = dataURItoBlob;




})();