MutliQRCode

PC端和移动端都可用的二维码识别

当前为 2023-05-27 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         MutliQRCode
// @namespace    https://greasyfork.org/zh-CN/users/1073349
// @version      0.1
// @description  PC端和移动端都可用的二维码识别
// @author       4ehex
// @match        *://*/*
// @grant        GM_addStyle
// @icon         data:image/svg+xml;base64,PHN2ZyBjbGFzcz0iaWNvbiIgc3R5bGU9IndpZHRoOiAxZW07aGVpZ2h0OiAxZW07dmVydGljYWwtYWxpZ246IG1pZGRsZTtmaWxsOiBjdXJyZW50Q29sb3I7b3ZlcmZsb3c6IGhpZGRlbjsiIHZpZXdCb3g9IjAgMCAxMDI0IDEwMjQiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBwLWlkPSI3NjA1Ij48cGF0aCBkPSJNMTg2LjAyNjY2NyAwaDY1MS45NDY2NjZRMTAyNCAwIDEwMjQgMTg2LjAyNjY2N3Y2NTEuOTQ2NjY2UTEwMjQgMTAyNCA4MzcuOTczMzMzIDEwMjRIMTg2LjAyNjY2N1EwIDEwMjQgMCA4MzcuOTczMzMzVjE4Ni4wMjY2NjdRMCAwIDE4Ni4wMjY2NjcgMHoiIGZpbGw9IiMzNjg5RjUiIHAtaWQ9Ijc2MDYiPjwvcGF0aD48cGF0aCBkPSJNMjEzLjMzMzMzMyAzMDQuNjRBOTAuODggOTAuODggMCAwIDEgMzA0LjIxMzMzMyAyMTMuMzMzMzMzaDkwLjg4djQyLjY2NjY2N0gzMDYuMzQ2NjY3YTQ1LjY1MzMzMyA0NS42NTMzMzMgMCAwIDAtNDYuNTA2NjY3IDQ4LjY0djkxLjczMzMzM0gyMTMuMzMzMzMzek0zOTYuOCA4MTAuNjY2NjY3SDMwNi4zNDY2NjdhOTAuNDUzMzMzIDkwLjQ1MzMzMyAwIDAgMS05MC44OC05MS4zMDY2Njd2LTkxLjczMzMzM2g0Ni41MDY2NjZ2OTEuNzMzMzMzQTQ1LjY1MzMzMyA0NS42NTMzMzMgMCAwIDAgMzA4LjA1MzMzMyA3NjhoOTAuODhhMjk4LjY2NjY2NyAyOTguNjY2NjY3IDAgMCAwLTIuMTMzMzMzIDQyLjY2NjY2N3pNODEwLjY2NjY2NyA3MTkuMzZBOTAuNDUzMzMzIDkwLjQ1MzMzMyAwIDAgMSA3MTcuNjUzMzMzIDgxMC42NjY2NjdINjI3LjJ2LTQ2LjkzMzMzNGg5MC40NTMzMzNhNDUuNjUzMzMzIDQ1LjY1MzMzMyAwIDAgMCA0Ni41MDY2NjctNDYuNTA2NjY2di05MS4zMDY2NjdIODEwLjY2NjY2N3pNMjEzLjMzMzMzMyA0ODcuNjhoNTk1LjJ2NDYuOTMzMzMzSDIxMy4zMzMzMzN6TTgxMC42NjY2NjcgMzk2LjM3MzMzM2gtNDguNjRWMzA0LjY0YTQ1LjY1MzMzMyA0NS42NTMzMzMgMCAwIDAtNDYuMDgtNDYuNTA2NjY3aC05MC44OFYyMTMuMzMzMzMzaDkwLjg4YTkwLjg4IDkwLjg4IDAgMCAxIDkwLjg4IDkxLjMwNjY2N3oiIGZpbGw9IiNGRkZGRkYiIHAtaWQ9Ijc2MDciPjwvcGF0aD48L3N2Zz4=
// @grant        unsafeWindow
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/jsQR.min.js
// @require      https://cdn.jsdelivr.net/npm/[email protected]/dist/html2canvas.min.js
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    //全局变量 被选中的图片元素
    var g_img_ele = null;

    //添加'识别二维码'按钮样式
    if (!isPhone()){
        GM_addStyle(`.idtfy_div{width:5.5vw;height:2.1vh;font-size:1vh;color:#000000;background:#F8F8FF;border-radius:1.5vh;border:0.12vh solid #f2cac9;line-height:2vh;text-align:center;vertical-align:middle;z-index:99999999;display:none;position:absolute;top:20;left:20;cursor:pointer;box-shadow:0.13vh 0.13vh 0.1vh #888888;}`);
    }
    else{
        GM_addStyle(`.idtfy_div{width:25vw;height:3vh;font-size:1.6vh;color:#000000;background:#F8F8FF;border-radius:1.5vh;border:0.14vw solid #f2cac9;line-height:3vh;text-align:center;vertical-align:middle;z-index:99999999;display:none;position:absolute;top:20;left:20;cursor:pointer;box-shadow:0.15vw 0.15vw 0.13vw #888888;}`);
    }
    //添加'识别二维码'按钮
    var identify_div = document.createElement('div');
    identify_div.id = 'identify_div';
    identify_div.className = 'idtfy_div';//👇添加一个图标
    identify_div.innerHTML = `<svg class="icon" style="width:1.3vh;height:1.3vh;vertical-align:middle;fill:currentColor;overflow:hidden" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3325"><path d="M613.888 715.264h-41.984C448.512 715.264 348.16 614.912 348.16 491.52s99.84-223.232 223.232-223.232h41.984c123.392 0 223.232 99.84 223.232 223.232 0.512 123.392-99.328 223.744-222.72 223.744z" fill="#CAD3FF" opacity=".2" p-id="3326"></path><path d="M873.984 940.032h-152.576c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h147.456v-147.456c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v152.576c0 25.088-20.48 46.08-46.08 46.08zM894.464 311.296c-14.336 0-25.6-11.264-25.6-25.6v-148.48h-147.456c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h152.576c25.6 0 46.08 20.48 46.08 46.08v153.6c0 13.824-11.264 25.6-25.6 25.6z m-20.48-174.08zM131.072 311.296c-14.336 0-25.6-11.264-25.6-25.6v-153.6c0-25.6 20.48-46.08 46.08-46.08h152.576c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6H156.672v148.48c0 13.824-11.776 25.6-25.6 25.6zM304.128 940.032H151.552c-25.6 0-46.08-20.48-46.08-46.08v-152.576c0-14.336 11.264-25.6 25.6-25.6s25.6 11.264 25.6 25.6v147.456h147.456c14.336 0 25.6 11.264 25.6 25.6s-11.264 25.6-25.6 25.6zM726.528 537.6H297.472c-14.336 0-25.6-11.264-25.6-25.6s11.264-25.6 25.6-25.6h429.056c14.336 0 25.6 11.264 25.6 25.6s-11.776 25.6-25.6 25.6z" fill="#4E63DD" p-id="3327"></path></svg> 识别二维码`;
    identify_div.onclick = OnClickedIdentifyBtn;
    document.body.appendChild(identify_div);

    if (!isPhone()){
        //电脑端 右键弹出 双击隐藏
        window.onmousedown = function(e) {
            if (e.button == 2) {//右键
                var clickedElement = e.target;
                if (GetQREle(clickedElement) != null){
                    document.getElementById("identify_div").style.top = (e.pageY + 10) + "px";
                    document.getElementById("identify_div").style.left = (e.pageX) + "px";
                    document.getElementById("identify_div").style.display = 'block';
                    g_img_ele = clickedElement;
                }
            }
        };

        window.ondblclick = function(e) {//双击隐藏按钮
            document.getElementById("identify_div").style.display = 'none';
        }
    }
    else{
        //移动端 监听长按事件
        let time_out = 0, touch_time = 600;
        window.addEventListener("touchstart", function(e){
            time_out = setTimeout(function(){
                var touchedElement = e.target;
                if (GetQREle(touchedElement) != null) {
                    document.getElementById("identify_div").style.top = (e.touches[0].pageY - 50) + "px";
                    document.getElementById("identify_div").style.left = (e.touches[0].pageX + 20) + "px";
                    document.getElementById("identify_div").style.display = 'block';
                    g_img_ele = touchedElement;
                }
            }, touch_time);//touch_time毫秒后弹出识别按钮

            //触碰其他地方则隐藏按钮
            if (e.target.id != 'identify_div'){
                g_img_ele = null;
                document.getElementById("identify_div").style.display = 'none';
            }
        });
        window.addEventListener("touchmove", function(e){
            // 如果触摸未达到 touch_time ms且开始移动,则清除计时器
            clearTimeout(time_out);
            time_out = 0;
        });
        window.addEventListener("touchend", function(e){
            // 如果触摸未达到 touch_time ms且离开屏幕,则清除计时器
            clearTimeout(time_out);
            time_out = 0;
        });
    }

    //通过UA判断是否是移动端
    function isPhone() {
        var info = navigator.userAgent;
        var isPhone = /mobile/i.test(info);
        return isPhone;
    }

    //从传入的元素中获取存有图片的元素 若没有则返回null
    function GetQREle(ele){
        let ret_ele = null;
        if (ele.tagName == 'DIV'){
            //遍历div的子元素看看是否有图片
            var childs = ele.childNodes;
            for(var i = childs.length - 1; i >= 0; i--) {
                if (childs[i].tagName == 'IMG' && childs[i].src != null){
                    ret_ele = childs[i];
                    break;
                }
            }
        }
        else if (ele.tagName == 'IMG' && ele.src != null){
            ret_ele = ele;
        }

        return ret_ele;
    }

    //通过html2canvs截图并识别
    function Html2CanvasAndIndentify(ele){
        html2canvas(ele,{
            useCORS: true, //开启跨域配置
            allowTaint: true, //允许跨域图片
        }).then(function(canvas) {
            var imgData = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height);

            const code = jsQR(imgData.data, imgData.width, imgData.height, {
                inversionAttempts: "dontInvert",
            });
            if (code == null) alert('识别失败!'); else alert(code.data);

        });
    }


    //'识别二维码'按钮事件
    function OnClickedIdentifyBtn(){
        if (g_img_ele == null){
            alert('未选中任何图片!');
        }
        else {
            Html2CanvasAndIndentify(g_img_ele);
        }
        document.getElementById("identify_div").style.display = 'none';
    }
})();