Greasy Fork is available in English.

鼠标悬停图片放大预览-大师兄

电脑端可以跟随鼠标悬停图片放大预览,找了很多图片放大的脚本,都没有一个能用的,只有自己写。大部分网站的图片都可以已支持悬浮放大了。完美适应大小屏幕,图片超大也会图片等比例自适应浏览器。鼠标跟随也优化。欢迎好评反馈,有时间就更新

질문, 리뷰하거나, 이 스크립트를 신고하세요.
// ==UserScript==
// @name        鼠标悬停图片放大预览-大师兄
// @date        05/27/2021
// @namespace    https://greasyfork.org/zh-CN/users/724782-caogen1207
// @match       *://*/*
// @version     4.1
// @author      大师兄 476116973@qq.com  VX:caogen
// @license     2022年1月8日22:30:21
// @description 电脑端可以跟随鼠标悬停图片放大预览,找了很多图片放大的脚本,都没有一个能用的,只有自己写。大部分网站的图片都可以已支持悬浮放大了。完美适应大小屏幕,图片超大也会图片等比例自适应浏览器。鼠标跟随也优化。欢迎好评反馈,有时间就更新
// @note        2.5 2021年10月4日更新超大图片显示问题
// @note        2.6 2021年10月14日解决某些网站不能正常使用问题
// @note        3.0 2021年11月6日已更新大部分网站不能识别图片放大功能
// @note        3.1 2022年10月8日18:42:41 解决淘宝缩略图问题,例如详情页里主图缩略图悬浮,猜你喜欢的悬浮放大出原图
// @note        3.2 2022年10月9日18:28:17 解决某些网站图片显示成直线问题
// @note        4.0 2022年10月10日12:33:13 修复了大图显示混乱问题;增加了有些不能放大的图片的功能;增加了天猫、微博直接放大出原图功能,不是放大缩略图
// @note        4.0 2022年10月10日22:58:10 增加了更多能悬停放大的图片;增加了B站视频封面直接放大出原图功能,不是放大缩略图。下一步计划添加下载快捷键,求问用什么快捷键好一些
// @run-at      document-idle
// @require     https://code.jquery.com/jquery-3.6.0.min.js
// @icon        http://inews.gtimg.com/newsapp_bt/0/14677352341/641
// @grant       none
// ==/UserScript==
(function() {
    console.log("鼠标悬停图片放大预览-大师兄");

    fangdatupian();
    function fangdatupian() {
        //添加图片盒子
        $(document.body).append("<div id='dashixiong_preview' style='display:none;pointer-events:none;padding:0px;margin:0px;left:0px;top:0px;background-color:#00000000;position:fixed;z-index:9999999998;'><img /></div>"); //弹出一个div里面放着图片
        jiantingimg();

    }

    function jiantingimg(){
        $("body").on("mouseenter mousemove mouseout", "img,div,picture", function(e){
            e.stopPropagation();
            let imgw,imgh,imgsrc;
            let target = e.target;


            if(e.type == "mouseenter"){
                console.log(target.nodeName, e);
                switch(target.nodeName){
                    case "IMG":
                        imgsrc = target.src;
                        break;
                    case "DIV":
                        if(target.dataset.role == "img"){
                            let img = target.parentNode.querySelector('img');
                            if (img) console.log(img);
                            imgsrc = img.src;
                        }else if(target.previousSibling && target.previousSibling.nodeName && target.previousSibling.nodeName == "IMG"){
                            imgsrc = target.previousSibling.src;
                        }else if (target.offsetParent && target.offsetParent.parentNode && target.offsetParent.parentNode.firstElementChild && target.offsetParent.parentNode.firstElementChild.nodeName == "IMG"){
                            imgsrc = target.offsetParent.parentNode.firstElementChild.src;
                        }else if(target.children[0] && target.children[0].localName == "img"){
                            imgsrc = target.children[0].src;
                        }else if(hasBg(target.offsetParent.children[0])){
                            imgsrc = window.getComputedStyle(target.offsetParent.children[0]).backgroundImage.replace(/url\("/i,'').replace(/"\)/i,'');
                        }else{
                            return;
                        }
                        break;
                    case "PICTURE":
                        imgsrc = target.querySelector("img").src;
                        break;
                    case "A":
                        if(/\.(jpg|png|jpeg|gif|webp)\b/.test(target.href)){
                            imgsrc = target.href;
                        }else if(/\.(jpg|png|jpeg|gif|webp)\b/.test(target.parentNode.href)){
                            imgsrc = target.parentNode.href;
                        }else{
                            return;
                        }
                        break;
                    case "SPAN":
                        if(target.nextElementSibling && target.nextElementSibling.nodeName == "IMG"){
                            imgsrc = target.nextElementSibling.src;
                        }else{
                            return;
                        }
                        break;
                    default :
                        console.log();
                }
                if(!imgsrc)return;

                let url = window.location.hostname;
                if(/weibo.com/i.test(url)){
                    if(/\/orj360\//i.test(imgsrc)){
                        imgsrc = imgsrc.replace(/orj360/i,'mw2000');
                    }
                }else if(/(taobao|tmall).com/i.test(url)){
                    //解决淘宝缩略图问题
                    if(/.(jpg|png|jpeg)_(\d+)x(\d+).jpg_.webp/i.test(imgsrc)){
                        imgsrc = imgsrc.replace(/_(\d+)x(\d+).jpg_.webp/i,'')
                    }else if(/.(jpg|png|jpeg)_(\d+)x(\d+)q(90|75|50)(s50)?.jpg_.webp/i.test(imgsrc)){
                        imgsrc = imgsrc.replace(/_(\d+)x(\d+)q(90|75|50)(s50)?.jpg_.webp/i,'')
                    }else if(/.(jpg|png|jpeg)_q(90|75).jpg/i.test(imgsrc)){
                        imgsrc = imgsrc.replace(/_q(90|75).jpg/i,'')
                    }else if(/.(jpg|png|jpeg)_(\d+)x(\d+).jpg/i.test(imgsrc)){
                        imgsrc = imgsrc.replace(/_(\d+)x(\d+).jpg/i,'')
                    }
                }else if(/bilibili.com/i.test(url)){
                    if(/@(\d+)w_(\d+)h_1c/i.test(imgsrc)){
                        imgsrc = imgsrc.replace(/@(\d+)w_(\d+)h_1c/i,'')
                    }
                }


                $("#dashixiong_preview img").attr("src", imgsrc).attr("style","width: auto").attr("style","height: auto");

                tupianweizhi(e, imgw, imgh);
                $("#dashixiong_preview").stop(true, false).show();
            }else if(e.type == "mousemove"){
                $("#dashixiong_preview img").attr("src", imgsrc).attr("style","width: auto").attr("style","height: auto");
                imgw = $("#dashixiong_preview img").width();
                imgh = $("#dashixiong_preview img").height();
                tupianweizhi(e, imgw, imgh);
            }else if(e.type == "mouseout"){
                $("#dashixiong_preview").stop(true, false).hide();
            };
        });
    }

    function tupianweizhi(e, img_width, img_height) {
        $("#dashixiong_preview img").width(img_width);
        $("#dashixiong_preview img").height(img_height);

        let jianxi = 20;
        let window_height = $(window).height();
        let window_width = $(window).width();
        if(window_height > window.screen.height)window_height = document.body.clientHeight;

        if (img_height > window_height || img_width > window_width) {
            if (window_width*img_height/img_width > window_height) {
                $("#dashixiong_preview img").css({
                    "height": window_height,
                    "width": img_width * window_height / img_height
                });
            }else{
                $("#dashixiong_preview img").css({
                    "height": img_height * window_width / img_width,
                    "width": window_width
                });
            };
        };

        img_height = $("#dashixiong_preview img").height();
        img_width = $("#dashixiong_preview img").width();

        if (img_height + e.clientY < window_height && img_width + e.clientX < window_width){
            //console.log("显示在鼠标右下");
            $("#dashixiong_preview").css({
                top: e.clientY + jianxi,
                left: (e.clientX + img_width + jianxi > window_width) ? window_width - img_width - jianxi : e.clientX + jianxi,
            });
        } else if (img_height + e.clientY > window_height && img_width + e.clientX < window_width) {
            //console.log("显示高度超过屏幕,显示在鼠标左右两侧");
            if (img_height + e.clientY + jianxi > window_height) {
                $("#dashixiong_preview").css({
                    top: (e.clientY - img_height - jianxi) < 0 ? 0 : e.clientY - img_height - jianxi,
                    left: ((e.clientX - img_width - jianxi) < 0 && e.clientX + jianxi + img_width > window_width) ? window_width - img_width - jianxi : e.clientX + jianxi
                });
            }
        } else if (img_width + e.clientX + jianxi > window_width && img_height + e.clientY < window_height) {
            //console.log("显示宽度超过屏幕,显示在鼠标上下两侧");
            $("#dashixiong_preview").css({
                top: (e.clientY - img_height - jianxi) < 0 ? 0 : e.clientY + jianxi,
                left: (e.clientX - img_width - jianxi) < 0 ? 0 : e.clientX - img_width - jianxi,
            });
        } else if (img_width + e.clientX > window_width && img_height + e.clientY > window_height) {
            //console.log("显示高度和宽度均超过屏幕");
            if (e.clientX - img_width - jianxi > 0 && e.clientY - img_height - jianxi > 0) {//左上角
                $("#dashixiong_preview").css({
                    top: e.clientY - img_height - jianxi,
                    left: e.clientX - img_width - jianxi,
                });
            } else if (e.clientX - img_width - jianxi < 0 && e.clientY - img_height - jianxi > 0) {//宽度超大左上角,左边固定
                $("#dashixiong_preview").css({
                    top: e.clientY - img_height - jianxi,
                    left: 0,
                });
            } else if (e.clientX - img_width - jianxi > 0 && e.clientY - img_height - jianxi < 0) {//高度超大左上角,顶边固定
                $("#dashixiong_preview").css({
                    top: 0,
                    left: e.clientX - img_width - jianxi,
                });
            } else if (e.clientX - img_width - jianxi < 0 && e.clientY - img_height - jianxi < 0) {//高宽均超大,固定左上角边
                $("#dashixiong_preview").css({
                    top: 0,
                    left: 0,
                });
            };

        }
    }

    function hasBg(node){
        if(node.nodeName == "HTML" || node.nodeName == "#document"){
            return false;
        }
        let nodeStyle = window.getComputedStyle(node);
        return node && nodeStyle.backgroundImage && /^\s*url\(\s*['"]?\s*[^a\s]/i.test(nodeStyle.backgroundImage);
    };

    function getImageWidth(img_url) {
        // 创建对象
        var img = new Image();
        // 改变图片的src
        img.src = img_url;
        // 判断是否有缓存
        if(img.complete){
            return [img.width,img.height];
        }else{
            // 加载完成执行
            img.onload = function(){
                return [img.width,img.height];
            };
        }
    }

    function Toast(msg,duration){
        duration=isNaN(duration)?3000:duration;
        let m = document.createElement('div');
        m.innerHTML = msg;
        m.style.cssText="max-width:60%;min-width: 150px;padding:0 14px;height: 40px;color: rgb(255, 255, 255);line-height: 40px;text-align: center;border-radius: 4px;position: fixed;top: 50%;left: 50%;transform: translate(-50%, -50%);z-index: 999999;background: rgba(0, 0, 0,.7);font-size: 16px;";
        document.body.appendChild(m);
        setTimeout(function() {
            let d = 0.5;
            m.style.webkitTransition = '-webkit-transform ' + d + 's ease-in, opacity ' + d + 's ease-in';
            m.style.opacity = '0';
            setTimeout(function() { document.body.removeChild(m) }, d * 1000);
        }, duration);
    }

    function getViewprotOffset() {
        if (window.innerWidth) {
            return [window.innerWidth,window.innerHeight]
        } else {
            if (document.compatMode == "BackCompat") {
                return [document.body.clientWidth, document.body.clientHeight]
            } else {
                return [document.documentElement.clientWidth, document.documentElement.clientHeight]
            }
        }
    }

})();