Html5QRCode扫描条形码+二维码+5秒没扫出后截图以文件扫描

目的:使用html2canvas画布去截取下来的图片,然后去尝试解析其图片用来识别条形码和二维码

 

代码:

<html>
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>scan</title>
    <style>
        button {
            display: block;
            width: 100%;
            margin: 6px;
            outline: none;
            height: 40px;
            line-height: 40px;
            color: #fff;
            background-color: #26a2ff;
            text-align: center;
            border-radius: 4px;
            border: none;
            cursor: pointer;
        }

        #qr-input-file {
            opacity: 0;
            filter: alpha(opacity=0);
            display: inline-block;
            width: 100%;
            height: 100%;
        }

        #upload-text {
            position: relative;
            bottom: 40px;
            user-select: none;
        }
    </style>
    <script src="~/easyui/jquery.min.js"></script>
    <script src="~/scan/html5-qrcode.min.js"></script>
    <script src="~/scan/html2canvas.min.js"></script>
</head>
<body>
    <div id="tempDiv"></div>
    <button id="num">0</button>
    <button id="refresh">刷新</button>
    <button id="scan">使用相机扫一扫方式</button>
    <button id="useLocal">
        <input type="file" id="qr-input-file" accept="image/*" value="使用文件方式">
        <span id="upload-text">使用文件方式</span>
    </button>
    <H3 id="readResult"></H3>
    <div id="reader" width="600px"></div>

    <canvas id="canvas" @*width="250" height="250"*@></canvas>
    <div id="imgDiv" style="width:250px;height:200px;"></div>
</body>
<script>
    function onScanSuccess(decodedText, decodedResult) {
        $('#readResult').html(decodedText + ":" + decodedResult);
    }
    function onScanFailure(error) {
        $('#readResult').html(error);
    }

    var num = 0;
    var trice = 0;
    var intervalSecond;
    function AddSecond() {
        if (trice == 0) {
            trice ++;
            intervalSecond = setInterval(function () {
                num++;
                $('#num').html(num);
            }, 1000); // 1000毫秒后执行
        }
    }
    function SubPicToCode(html5QrCode) {
        //开始截图模拟文件识别
        clearInterval(intervalSecond);
        const video = document.querySelector('video');
        //const canvas2 = $('#canvas')[0];
        //const context = canvas.getContext('2d');

        const canvas = document.getElementById('canvas');
        const context = canvas.getContext('2d');
        var canvasWidth = $('video').width();
        var canvasHeight = $('video').height();
        $('#canvas').css('width', canvasWidth);
        $('#canvas').css('height', canvasHeight);
        //从视频流中取帧并绘制到canvas上
        context.drawImage(video, 0, 0, canvas.width, canvas.height);

        //关闭摄像头
        html5QrCode.stop().then((ignore) => {
            // QR Code scanning is stopped.
        }).catch((err) => {
            // Stop failed, handle it.
        });

        convert_elements_to_image_and_download(html5QrCode,["#canvas"]);
    }

    function Clear() {
        num = 0;
        trice = 0;
        $('#num').html(num);
        $('#imgDiv').html('');
        $('#canvas').width(0);
        $('#canvas').height(0);
        clearInterval(intervalSecond);
    }

    $(function () {
        $('#refresh').click(function () {
            location.reload();
        });

        $('#scan').click(function () {
            $('#readResult').html("");
            Clear();
            const html5QrCode = new Html5Qrcode("reader");
            const qrCodeSuccessCallback = (decodedText, decodedResult) => {
                /* handle success */
                $('#readResult').html("扫描成功:" + decodedText);
                //关闭摄像头
                html5QrCode.stop().then((ignore) => {
                    // QR Code scanning is stopped.
                }).catch((err) => {
                    // Stop failed, handle it.
                });
            };
            
            const qrCodeFailCallback = (error) => {
                /* handle Fail */
                $('#readResult').html("扫描失败:" + error);
                if (num == 0)
                    AddSecond();
                else if (num >= 5)
                    SubPicToCode(html5QrCode);
                //关闭摄像头
                //html5QrCode.stop().then((ignore) => {
                //    // QR Code scanning is stopped.
                //}).catch((err) => {
                //    // Stop failed, handle it.
                //});
            };

            const config = { fps: 10, qrbox: { width: 250, height: 250 } };

            // If you want to prefer front camera
            //html5QrCode.start({ facingMode: "user" }, config, qrCodeSuccessCallback);

            // If you want to prefer back camera
            html5QrCode.start({ facingMode: "environment" }, config, qrCodeSuccessCallback, qrCodeFailCallback)
                .catch((err) => {
                    $('#readResult').html("扫描异常:" + err);
                    //关闭摄像头
                    html5QrCode.stop().then((ignore) => {
                        // QR Code scanning is stopped.
                    }).catch((err) => {
                        // Stop failed, handle it.
                    });
                });

            // Select front camera or fail with `OverconstrainedError`.
            //html5QrCode.start({ facingMode: { exact: "user"} }, config, qrCodeSuccessCallback);

            // Select back camera or fail with `OverconstrainedError`.
            //html5QrCode.start({ facingMode: { exact: "environment"} }, config, qrCodeSuccessCallback);

        })
        //选择文件扫描
        $('#qr-input-file').change(function (e) {
            $('#readResult').html("");
            Clear();
            const html5QrCode = new Html5Qrcode("reader");
            if (e.target.files.length == 0) {
                // No file selected, ignore
                return;
            }

            const imageFile = e.target.files[0];
            // Scan QR Code
            html5QrCode.scanFile(imageFile, true)
                .then(decodedText => {
                    // success, use decodedText
                    //console.log(decodedText);
                    $('#readResult').html(decodedText);
                    $('#qr-input-file').val('');
                })
                .catch(err => {
                    // failure, handle it.
                    console.log(`Error scanning file. Reason: ${err}`)
                    $('#readResult').html("扫描错误:" + err);
                });
        });

    })

    //截图
    async function convert_elements_to_image_and_download(html5QrCode,array_ele_selectors, is_vertical = true) {
        // 元素img data保存列表
        let array_ele_img_datas = new Array();
        // 元素img 宽度保存列表
        let array_ele_img_widths = new Array();
        // 元素img 高度保存列表
        let array_ele_img_heights = new Array();
        for (let i = 0; i < array_ele_selectors.length; i++) {
            let selector = document.querySelector(array_ele_selectors[i]);
            array_ele_img_datas.push(await generate_img_data(selector));
            array_ele_img_widths.push(get_ele_width(selector));
            array_ele_img_heights.push(get_ele_height(selector));
        }

        let img_data = null;
        if (is_vertical) {
            //垂直排列合并元素图片
            img_data = await vertical_merge_elements_pic(
                array_ele_img_datas,
                array_ele_img_widths,
                array_ele_img_heights);
        } else {
            console.log("Not support yet!");
            return false;
        }
        //show_picture(img_data);

        var imgObject = new Image();
        imgObject.src = img_data;
        //call the methods that will create a 64-bit version of thumbnail here.
        var canvasWidth = $('#canvas').width();
        var canvasHeight = $('#canvas').height();
        var x = (canvasWidth - 250) / 2;
        var y = (canvasHeight - 250) / 2;
        SubPointPic(html5QrCode,x,y,250,250);
    }

    function SubPointPic(html5QrCode,xOffset, yOffset, width, height) {
        const targetElement = document.querySelector("#canvas");
        //截取指定坐标图片
        html2canvas(targetElement, {
            x: xOffset,
            y: yOffset,
            width: width,
            height: height,
        }).then((canvas) => {
            // 获取canvas图像数据
            const imageData = canvas.toDataURL("image/jpeg");
            // 进一步处理图像数据
            //place image in appropriate div
            document.getElementById("imgDiv").innerHTML = '<img id="imgCan" alt="" src="' + imageData + '" />';
            Base64ToCode(html5QrCode,imageData, "123.png");
        });

    }

    //base64转File
    function Base64ToCode(html5QrCode, base64String, fileName) {
        const arr = base64String.split(',');
        const mime = arr[0].match(/:(.*?);/)[1];
        const bstr = atob(arr[1]);
        let n = bstr.length;
        const u8arr = new Uint8Array(n);

        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        const imageFile = new File([u8arr], fileName, { type: mime });
        // Scan QR Code

        //const html5QrCode = new Html5Qrcode("reader");
        html5QrCode.scanFile(imageFile, true)
            .then(decodedText => {
                // success, use decodedText
                //console.log(decodedText);
                alert("图片解析的");
                $('#readResult').html(decodedText);

                //$('#qr-input-file').val('');
            })
            .catch(err => {
                // failure, handle it.
                console.log(`Error scanning file. Reason: ${err}`)
                $('#readResult').html("扫描错误:" + err);
            });
    }

    async function vertical_merge_elements_pic(array_ele_img_datas,
        array_ele_img_widths,
        array_ele_img_heights) {
        // 垂直方向合并各个元素图片

        let total_height = 0;
        let max_width = 0;
        for (let i = 0; i < array_ele_img_datas.length; i++) {
            total_height += array_ele_img_heights[i];
            if (max_width < array_ele_img_widths[i]) {
                max_width = array_ele_img_widths[i];
            }
        }

        // 创建canvas元素
        var canvas = document.createElement('canvas');
        // 设置canvas的宽高
        canvas.width = max_width;
        canvas.height = total_height;
        // 获取canvas的2D绘图上下文
        var ctx = canvas.getContext('2d');

        //在canvas上绘制图片
        let already_have_height = 0;
        for (var j = 0; j < array_ele_img_datas.length; j++) {
            await new Promise((resolve, reject) => {
                let tmp_img = new Image();
                tmp_img.onload = () => {
                    ctx.drawImage(tmp_img, 0, already_have_height);
                    resolve();
                };
                tmp_img.onerror = reject;
                tmp_img.src = array_ele_img_datas[j];
            });
            already_have_height += array_ele_img_heights[j];
        }

        // 返回合并后的图片
        return canvas.toDataURL();
    }

    function get_ele_width(element) {
        //获取元素宽度
        return element.clientWidth;
    }

    function get_ele_height(element) {
        //获取元素高度
        return element.clientHeight;
    }


    async function generate_img_data(element) {
        //返回的是图片base64编码
        try {
            // html2canvas是异步执行的
            // 使用await关键字等待html2canvas的Promise完成
            const canvas = await html2canvas(element);
            console.log("Canvas generated:", canvas);
            return canvas.toDataURL();
        } catch (error) {
            console.error('Error generating canvas:', error);
        }
    }

    function show_picture(data_url) {
        // 创建一个a标签用于下载
        const a = document.createElement('img');
        a.src = data_url;
        // 设置下载的文件名
        //a.download = 'screenshot.png';
        // 触发点击事件
        //a.click();
        $('#tempDiv').html(a);
    }


    function picture_toFile(data_url) {
        // 创建一个a标签用于下载
        const a = document.createElement('input');
        a.src = data_url;
        // 设置下载的文件名
        //a.download = 'screenshot.png';
        // 触发点击事件
        //a.click();
        $('#tempDiv').append(a);
    }

    function download_picture(data_url) {
        // 创建一个a标签用于下载
        const a = document.createElement('a');
        a.href = data_url;
        // 设置下载的文件名
        a.download = 'screenshot.png';
        // 触发点击事件
        a.click();
    }

    //File转base64
    function fileToBase64(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (event) => {
                resolve(event.target.result);
            };
            reader.onerror = reject;
            reader.readAsDataURL(file); // 读取文件为DataURL
        });
    }

    //base64转File
    function base64ToFile(base64String, fileName) {
        const arr = base64String.split(',');
        const mime = arr[0].match(/:(.*?);/)[1];
        const bstr = atob(arr[1]);
        let n = bstr.length;
        const u8arr = new Uint8Array(n);

        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }

        return new File([u8arr], fileName, { type: mime });
    }
</script>
</html>

 

结论:效果不理想,预计还需要对截取的图片进行数据流分析,进而对文件清晰度的还原。(OpenCV等)

 

posted @ 2024-11-18 09:11  蜗牛的礼物  阅读(6)  评论(0编辑  收藏  举报