Greasy Fork is available in English.

Zoom In Twitter Image

Support 2019 new UI Twitter only.

2019/07/20時点のページです。最新版はこちら。

このスクリプトの質問や評価の投稿はこちら通報はこちらへお寄せください。
// ==UserScript==
// @name         Zoom In Twitter Image
// @version      1.0.8
// @description  Support 2019 new UI Twitter only.
// @author       Hayao-Gai
// @namespace	 https://github.com/HayaoGai
// @icon         https://i.imgur.com/M9oO8K9.png
// @include      https://twitter.com/*
// @require      http://code.jquery.com/jquery-3.4.1.slim.min.js
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    const $ = window.jQuery;
    const urlLoad = "https://i.imgur.com/hXeIJqw.gif";
    let img, push, image;
    let showing = false;

    $(document).ready(() => {
        createZoom();
        observeSystem();
        detectAddress();
        detectSwitch();
    });

    // 定義 Zoom
    function createZoom() {
        img = $("<img/>").css({
            "position": "fixed",
            "width": document.documentElement.clientWidth + "px",
            "height": document.documentElement.clientHeight + "px",
            "pointerEvents": "none",
            "display": "inline",
            "opacity": "0",
            "transition": "opacity 0.4s"
        }).appendTo("body");
    }

    // 觀察文件是否產生變化
    function observeSystem() {
        setTimeout(() => {
            const h1 = $("section").find("H1");
            const title = $("title");
            if (h1.length !== 2 || title.length === 0) observeSystem();
            else {
                // 獲取目標
                const target1 = [...h1[0].parentElement.childNodes].filter(child => child.tagName !== "H1")[0].childNodes[0].childNodes[0];
                const target2 = title[0];
                // 先執行一次
                setTimeout(addListener, 1000);
                // 建立觀察者,文件有變化就執行下列函式
                const mutation = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver; //前綴
                const observer = new mutation(addListener);
                // 設定觀察選項
                const config = { attributes: true, childList: true, characterData: true };
                // 開始觀察
                observer.observe(target1, config); //時間軸
                observer.observe(target2, config); //標籤頁
            }
        }, 500);
    }

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

    // 偵測上一頁、下一頁
    function detectSwitch() {
        window.addEventListener("popstate", observeSystem);
    }

    // 增加監聽的物件
    function addListener() {
        if (location.href.match("photo/1")) return; //點進圖片後,不做放大效果
        // 縮圖
        $(".css-9pa8cd").each((index, image) => {
            $(image).on("mousemove", showImage);
            $(image).on("mouseleave", hideImage);
        });
        // 展開按鈕
        $('[role="button"]').each((index, button) => {
            $(button).on("click", observeSystem);
        });
        // 上方標籤
        $('[role="tab"]').each((index, tab) => {
            $(tab).on("click", () => { setTimeout(() => observeSystem, 3000); });
        });
    }

    // 顯示圖片
    function showImage() {
        if (showing) return;
        showing = true;
        const url = getImage(this.src);
        image = new Image();
        image.onload = () => {
            // 調整圖片寬高
            const w = image.width;
            const h = image.height;
            const clientW = document.documentElement.clientWidth;
            const clientH = document.documentElement.clientHeight;
            const condition1 = w > clientW;
            const condition2 = h > clientH;
            if (condition1 && condition2) {
                const rate = clientH / h;
                const new_w = w * rate;
                const new_h = clientH;
                if (new_w > clientW) {
                    const rate2 = clientW / new_w;
                    const new_w2 = clientW;
                    const new_h2 = new_h * rate2;
                    img.css({ "width": new_w2 + "px", "height": new_h2 + "px" });
                } else {
                    img.css({ "width": new_w + "px", "height": new_h + "px" });
                }
            } else if (condition1) {
                const rate3 = clientW / w;
                const new_h3 = h * rate3;
                img.css({ "width": clientW + "px", "height": new_h3 + "px" });
            } else if (condition2) {
                const rate4 = clientH / h;
                const new_w4 = w * rate4;
                img.css({ "width": new_w4 + "px", "height": clientH + "px" });
            } else {
                img.css({ "width": w + "px", "height": h + "px" });
            }
            // 圖片位置
            let left = clientW / 2 - img.width() / 2;
            let top = clientH / 2 - img.height() / 2;
            if (left < 0) left = 0;
            if (top < 0) top = 0;
            // 調整圖片屬性
            img.attr("src", url);
            img.css({
                "left": left + "px",
                "top": top + "px",
                "display": "inline",
                "opacity": "1"
            });
        };
        image.src = url; //因不明原因,必須將這行寫在後面
    }

    // 取得圖片網址
    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() {
        showing = false;
        image.src = null;
        image.onload = null;
        img.css({
            "display": "none",
            "opacity": "0"
        });
    }

})();