Greasy Fork is available in English.

Zoom In Twitter Image

Support 2019/4/23 new UI Twitter.

נכון ליום 26-04-2019. ראה הגרסה האחרונה.

// ==UserScript==
// @name         Zoom In Twitter Image
// @version      1.0.0
// @description  Support 2019/4/23 new UI Twitter.
// @author       Hayao-Gai
// @namespace	 https://github.com/HayaoGai
// @icon         https://i.imgur.com/M9oO8K9.png
// @include      https://twitter.com/*
// @grant        none
// ==/UserScript==

(function() {
    "use strict";

    // 定義 Hover
    let hover = false;
    let block = document.createElement("div");
    block.style.position = "fixed";
    block.style.width = document.documentElement.clientWidth + "px";
    block.style.height = document.documentElement.clientHeight + "px"; //同視窗大小
    block.style.left = "0px";
    block.style.top = "0px"; //擺在正中間
    block.style.pointerEvents = "none";
    block.style.backgroundPosition = "center center";
    block.style.backgroundRepeat = "no-repeat";
    block.style.display = "none";
    block.style.opacity = "0";
    block.style.transition = "opacity 0.3s";
    document.body.appendChild(block);

    // 視窗縮放
    window.onresize = function() {
        block.style.width = document.documentElement.clientWidth;
        block.style.height = document.documentElement.clientHeight;
    };

    // 偵測是否僅切換地址
    let pushState = history.pushState;
    history.pushState = function () {
        pushState.apply(history, arguments);
        waitLoaded();
    };

    // 偵測上一頁、下一頁
    window.addEventListener("popstate", waitLoaded);

    // 觀察文件是否產生變化
    waitLoaded(); //等待文件讀取
    const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; //前綴
    function waitLoaded() {
        const section = document.getElementsByTagName("section");
        setTimeout(() => {
            if (section.length !== 2) waitLoaded();
            else {
                //console.log("change!");
                const target = section[0].children[1].children[0].children[0]; //取出會產生變化的節點
                addListener();
                const observer = new MutationObserver(e => { //建立觀察者,文件有變化就執行下列函式
                    //console.log("change!");
                    addListener();
                });
                const config = { attributes: true, childList: true, characterData: true }; //設定觀察選項
                observer.observe(target, config); //開始觀察
            }
        }, 500);
    }

    // 增加監聽的物件
    function addListener() {
        const image = document.getElementsByTagName("img");
        const button = document.querySelectorAll('[role="button"]');
        const tab = document.querySelectorAll('[role="tab"]');
        for (let i = 0; i < image.length; i++) mouseListener(image[i]);
        for (let i = 0; i < button.length; i++) clickListener(button[i]);
        for (let i = 0; i < tab.length; i++) clickListener(tab[i]);
    }

    // 監聽:滑鼠移至上方
    function mouseListener(element) {
        if (element.src.match("https://pbs") !== null) {
            element.addEventListener("mousemove", showImage);
            element.addEventListener("mouseleave", hideImage);
        }
    }

    // 監聽:滑鼠點按
    function clickListener(element) {
        element.addEventListener("click", waitLoaded);
    }

    // 元素位置
    function getPosition(element) {
        const rect = element.getBoundingClientRect();
        return {
            left: rect.left + window.scrollX,
            top: rect.top + window.scrollY
        };
    }

    // 顯示圖片
    let waitImage;
    function showImage() {
        if (!hover) {
            hover = true;
            const url = getImage(this.src);
            let newImg = new Image();
            newImg.src = url;
            waitImage = setTimeout(() => {
                const w = newImg.width;
                const h = newImg.height;
                const clientW = document.documentElement.clientWidth;
                const clientH = document.documentElement.clientHeight;
                // 縱圖(含正方形)
                if (w <= h && h > clientH) block.style.backgroundSize = "auto " + clientH + "px";
                // 橫圖
                else if (w > h && w > clientW) block.style.backgroundSize = clientW + "px auto";
                // 標準大小
                else block.style.backgroundSize = "auto auto";
                block.style.backgroundImage = "url(" + url + ")";
                block.style.display = "inline";
                block.style.opacity = "0";
                getComputedStyle(block).opacity;
                block.style.opacity = "1";
            }, 300);
        }
    }

    // 取得圖片
    function getImage(url) {
        const m1 = url.split("/");
        let newUrl = "https://pbs.twimg.com/";
        // 一般圖
        if (m1[3].match("media") !== null) {
            for (let i = 3; i < m1.length; i++) {
                if (i !== m1.length - 1) newUrl += m1[i] + "/";
                else newUrl += m1[i].split("&")[0] + "&name=orig";
            }
        }
        // 使用者頭像
        else if (m1[3].match("profile") !== null) {
            for (let i = 3; i < m1.length; i++) {
                if (i !== m1.length - 1) newUrl += m1[i] + "/";
                else {
                    const m2 = m1[i].split("_");
                    for (let i = 0; i < m2.length; i++) {
                        if (i === 0) newUrl += m2[i];
                        else if (i !== m2.length - 1) newUrl += "_" + m2[i];
                        else newUrl += "." + m2[i].split(".")[1];
                    }
                }
            }
        }
        // 影片不放大縮圖
        else newUrl = null;

        return newUrl;
    }

    // 隱藏圖片
    function hideImage() {
        clearTimeout(waitImage);
        hover = false;
        block.style.display = "none";
        block.style.opacity = "0";
    }
})();