在 IE8+ 中生成二维码(jsqr + excanvas,IE5适用,附文件)
本文最后更新于32 天前,其中的信息可能已经过时,如有错误请发送至评论区或邮箱alore@can6.top

最近在一个老项目中,需要在 IE8 环境下生成二维码。原本以为用个 QR 库搞定就行,结果遇到各种“Canvas 不支持”、“对象不支持此属性或方法” 的报错。
本文记录了整个问题的排查与最终封装方案,希望能帮到还在与 IE8 搏斗的朋友。

问题背景

我们项目要在旧版浏览器(特别是 IE8)中动态生成二维码,用的是开源的 jsqr(官方地址:https://www.jsqr.de/encode.html)。
在现代浏览器上一切正常,但到了 IE8 —— 页面直接报错:

对象不支持此属性或方法: getContext

也就是说:

IE8 压根不支持 Canvas!
而 jsqr 默认是基于 Canvas 绘图的。

调试准备

IE8调试方法有很多种,可以开一个虚拟机,我这里直接使用Edge的Internet Explorer兼容模式,不需要安装任何额外的软件。

可能是运气不好,原来一直存在的快捷选项在我想要调试的时候突然不见了,

于是又去找,最终找到了开启方法:https://learn.microsoft.com/zh-cn/answers/questions/5606783/142-0-3595-53-(-)-(64-)edge

在这里加入要调试的页面地址就行了

调试开发者工具开启方法:
Win + R 运行:

%systemroot%\system32\f12\IEChooser.exe

第一次尝试:直接用 jsqr

最初的代码结构大致如下,基本是从官网粘贴下来的:

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>QR Test IE8+ Compatible</title>
    <script src="./jsqr-1.0.3-min.js"></script>
</head>

<body>
<div id="container">container</div>

<script>
    var qr = new JSQR();

    var code = new qr.Code();
    code.encodeMode = code.ENCODE_MODE.BYTE;
    code.version = code.DEFAULT;
    code.errorCorrection = code.ERROR_CORRECTION.H;

    var input = new qr.Input();
    input.dataType = input.DATA_TYPE.URL;
    input.data = {
        "url": "jsqr.de"
    };

    var matrix = new qr.Matrix(input, code);

    var canvas = document.createElement('canvas');
    canvas.setAttribute('width', matrix.pixelWidth);
    canvas.setAttribute('height', matrix.pixelWidth);
    canvas.getContext('2d').fillStyle = 'rgb(0,0,0)';
    matrix.draw(canvas, 0, 0);
    document.getElementById('container').appendChild(canvas);
</script>
</body>
</html>

在 Chrome / Edge 下一切正常,但在 IE8:

报错:语法错误

查了一下之后发现我的 jsqr 版本1.0.3 ,源代码中包含ES6+语法,于是我就使用Babel将它编译成ES5版本。


第二次尝试:使用ES5版本jsqr

代码基本没变,把引入的原始js库改成了我编译之后的ES5版本

    <!-- ES5 版 JSQR 库 -->
    <script src="./jsqr-1.0.3-es5.js"></script>

结果仍然报错:

    canvas.setAttribute('width', matrix.pixelWidth);
    canvas.setAttribute('height', matrix.pixelWidth);
    canvas.getContext('2d').fillStyle = 'rgb(0,0,0)';  // 这里在 IE8 报错:对象不支持此属性或方法 getContext
    matrix.draw(canvas, 0, 0);
    document.getElementById('container').appendChild(canvas);

第三次尝试:引入 excanvas.js

查资料后发现:
IE8 可以通过一个微软早期的兼容层 —— excanvas.js 来模拟 Canvas 功能。

于是我加上:

<!--[if lt IE 9]>
<script src="./excanvas.js"></script>
<![endif]-->

并在创建 canvas 后初始化:

    var canvas = document.createElement('canvas');
    if (typeof G_vmlCanvasManager !== 'undefined') {
        G_vmlCanvasManager.initElement(canvas);
    }
    canvas.setAttribute('width', matrix.pixelWidth);
    canvas.setAttribute('height', matrix.pixelWidth);
    canvas.getContext('2d').fillStyle = 'rgb(0,0,0)';
    matrix.draw(canvas, 0, 0);
    document.getElementById('container').appendChild(canvas);

这一步之后,IE8 确实没有报错了,但不知为何仍然加载不出来二维码,不过元素的宽高确实出来了。


第四次尝试:调整canvas生成时机(成功)

再次查阅资料,找到一篇文章https://blog.csdn.net/weixin_42629522/article/details/153745582,文章写的非常详细,我也了解到exCanvas的初始化逻辑和时机非常重要,参考此文章我把代码顺序调整了一下。

    var canvas = document.createElement('canvas');
    document.getElementById('container').appendChild(canvas); // 创建元素操作移至初始化之前
    if (typeof G_vmlCanvasManager !== 'undefined') {
        G_vmlCanvasManager.initElement(canvas);
    }
    canvas.setAttribute('width', matrix.pixelWidth);
    canvas.setAttribute('height', matrix.pixelWidth);
    canvas.getContext('2d').fillStyle = 'rgb(0,0,0)';
    matrix.draw(canvas, 0, 0);

确实也可以正常显示了


封装

在成功调试过后我也把代码封装了一下,包括原jsqr的各个参数都重新封装了,包括其他的依赖一并All in One,接着暴露出函数QRGenerator,直接生成,方便后续使用,参数名除了前两个,其他全部沿用jsqr官网的参数名。

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>QR Test IE8+ Compatible</title>

    <script src="jsqr-ie.mix.js"></script>
</head>

<body>
<div id="container">container</div>

<script>
    QRGenerator(
        containerId = 'container',
        text = 'qr for IE8',
        {
            version: 1,
            errorCorrection: 'M',
            scale: 4,
            margin: 4,
            fgColor: '#000000',
            bgColor: 'transparent'
        }
    );
</script>
</body>
</html>


参考资料

在摸索过程中,我参考了两篇很有帮助的文章:

  1. jquery.qrcode 生成二维码并解决 canvas 在 IE8 兼容问题
  2. 生成二维码并下载二维码(兼容 IE 浏览器)

封装混合文件

已上传至github,项目地址:https://github.com/Alore111/jsqr-for-IE8

导入方法:

下载混合源文件或使用CDN导入,注意放在文件最开始的地方:

    <!--方法1:下载引用源混合文件-->
    <script src="jsqr-ie.mix.js"></script>

    <!--方法2:使用在线CDN-->
    <script src="https://cdn.jsdelivr.net/gh/Alore111/jsqr-for-IE8@0.0.1/jsqr-ie.mix.js"></script>

更多好玩意请到主页瞧瞧
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇