专栏首页张戈的专栏利用JS生成二维码图片,优化WEB性能及页面加载速度

利用JS生成二维码图片,优化WEB性能及页面加载速度

移动互联网的蓬勃发展绝对离不开二维码的“推波助澜”,一张小小的图片,省去了繁琐的苦逼输入,也拉近了 PC 端和移动端的距离!虽然是东洋人最初发明的,但我还是要给 32 个赞!

一、意淫场景

2 年前接触网站建设后,二维码也进入了我折腾的范围,当时意淫了这样一个场景:当用户首次在别人电脑上看到我们的网站时,突然有事要离开,但是这个网页内容很赞,实在难以割舍,他该怎么办?

我继续意淫了多个解决办法:

  • ①、复制这个网页,通过 QQ 发送到我的设备(那时候貌似还没有这个功能。。。)
  • ②、收藏到类似 QQ 云收藏等在线收藏夹,或保存为文本存在云盘,以后再看
  • ③、死记硬背也要记住这个网页地址,然后回家继续看
  • ④、赶紧掏出手机,在手机浏览器里面输入网页地址继续看
  • 。。。。
  • N、尼玛这网页为毛就不能提供一个二维码,让我用 QQ 浏览器扫一扫继续看呢?

很明显,在这种场景下,网页上如果能提供一个二维码就能给网站增加一个忠实访客,甚至是粉丝。

二、后台实现

我这人把,技术不行,但只要有想法就立马付诸实践,认为技术再难也不会是瓶颈。

博客用的语言是 php,因为第一时间用 php 实现了这个功能,应用到网站就是这个样子:

源码也非常简单,感兴趣的看下:https://zhangge.net/5031.html

三、前台实现

本来这个 PHP 二维码用得挺好的,反正做了 CDN 缓存,速度负载都不用考虑。最近在一个国外的网站看一个源码的时候,好奇的看看网页的二维码是什么地址是,发现居然是 canvas 生成的!

是咯,为毛之前我没想到 JS 生成二维码这一茬呢?

果然还是想法和见识更重要啊!知道有这个途径,怎么实现基本是小菜一碟了。

顺手百度了一下,果然一堆教程,而且个个历史悠久,看来自己 out 怪不得别人。

实现很简单,DEMO 如下:

<html>
<head>
  <meta charset="utf-8">
  <script src="//cdn.bootcss.com/jquery/1.8.2/jquery.min.js"></script>
  <script src="//cdn.bootcss.com/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
</head>
<body>
 <div id="output"></div>
 <script type="text/javascript">
   content = 'https://zhangge.net/';
   $('#output').qrcode({
       width: 200,
       height: 200,
       render: "canvas",
       correctLevel: 0,
       text: content
   });
</script>
</body>
</html>

丢到 SAE 试了下,效果还不错:http://atools.sinaapp.com/demo.html

更多参数如下:

render   : "canvas",//设置渲染方式  
width       : 256,     //设置宽度  
height      : 256,     //设置高度  
typeNumber  : -1,      //计算模式  
correctLevel    : QRErrorCorrectLevel.H,//纠错等级  
background      : "#ffffff",//背景颜色  
foreground      : "#000000" //前景颜色

四、中文兼容

从分享这个教程的博客那知道,上述 JS 生成二维码是不支持中文内容的,而少数个人博客可能会使用中文的 url 路径,那么就不适用了。

其实,要解决也挺简单,只要二维码编码前把字符串转换成 UTF-8 即可。

博主也提供相关 JS 转换代码:

function utf16to8(str) {  
    var out, i, len, c;  
    out = "";  
    len = str.length;  
    for(i = 0; i < len; i++) {  
    c = str.charCodeAt(i);  
    if ((c >= 0x0001) && (c <= 0x007F)) {  
        out += str.charAt(i);  
    } else if (c > 0x07FF) {  
        out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));  
        out += String.fromCharCode(0x80 | ((c >>  6) & 0x3F));  
        out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));  
    } else {  
        out += String.fromCharCode(0xC0 | ((c >>  6) & 0x1F));  
        out += String.fromCharCode(0x80 | ((c >>  0) & 0x3F));  
    }  
    }  
    return out;  
}

因此,如果内容含有中文,就需要用这个函数先转码,比如前文的 DEMO 修改如下:

<html>
<head>
  <meta charset="utf-8">
  <script src="//cdn.bootcss.com/jquery/1.8.2/jquery.min.js"></script>
  <script src="//cdn.bootcss.com/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>
</head>
<body>
 <div id="output"></div>
 <script type="text/javascript">
  function utf16to8(str) {
    var out, i, len, c;
    out = "";
    len = str.length;
    for (i = 0; i < len; i++) {
        c = str.charCodeAt(i);
        if ((c >= 0x0001) && (c <= 0x007F)) {
            out += str.charAt(i);
        } else if (c > 0x07FF) {
            out += String.fromCharCode(0xE0 | ((c >> 12) & 0x0F));
            out += String.fromCharCode(0x80 | ((c >> 6) & 0x3F));
            out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
        } else {
            out += String.fromCharCode(0xC0 | ((c >> 6) & 0x1F));
            out += String.fromCharCode(0x80 | ((c >> 0) & 0x3F));
        }
    }
    return out;
}
content = utf16to8('手机扫一扫,精彩随声带!');
$('#output').qrcode({
    width: 200,
    height: 200,
    render: "canvas",
    correctLevel: 0,
    text: content
});
</script>
</body>
</html>

参考文章:http://suflow.iteye.com/blog/1687396

五、Begin 主题

Ps:哈,突然发现鸟哥博客已经用上了,看来我们想到一起去了,相信 begin 新版本就会集成。

说了半天代码和 demo,可能还是有很多朋友不会用,下面再简单介绍下把 js 生成二维码集成到 Begin 的方法。

Begin 还是在上几个版本就已经集成了二维码图片功能,不过用的是外部 api 生成的,加载速度差强人意。当然,到了张戈博客,第一时间就换成了自建的php 二维码 api了。

现在 get 到了新技能,所以我也第一时间也将博客的二维码改成了 js 方式了,修改很简单:

①、加载 js 代码:

<script src="//cdn.bootcss.com/jquery.qrcode/1.0/jquery.qrcode.min.js"></script>

将上述代码添加到 Begin 主题的 header.php 或 footer.php 当中(也可以将上述 js 文件的内容合并到主题的全局 js,比如 scripts.js)。

②、修改 php 代码:

编辑 begin/inc/scroll.php 这个文件,如下修改即可:

<ul id="scroll">
    <?php if (zm_get_option('qr_img')) { ?><li><a class="qr" title="二维码"><i class="fa fa-qrcode"></i></a></li><?php } ?>
	<li><a class="scroll-t" title="返回顶部"><i class="fa fa-angle-up"></i></a></li>
	<?php if(is_single() || is_page()) { ?><li><a class="scroll-c" title="评论"><i class="fa fa-comment-o"></i></a></li><?php } ?>
	<li><a class="scroll-b" title="转到底部"><i class="fa fa-angle-down"></i></a></li>
</ul>

<?php if (zm_get_option('qr_img')) { ?>
    <!-- table模式下修复点阵过于分散导致二维码扫描失效问题 -->
    <style>.qr-img td { border: none;padding: 0;}</style>
    <span class="qr-img">
    <img class="alignnone" src="//res.zgboke.com/favicon.ico" style="position: absolute;top: 75px;right: 75px;width: 30px;height: 30px;">
    <div id="qr-img"></div>
    <div id="floatbtn-qr-msg">手机扫一扫 精彩随身带</div>
    </span>
     <script type="text/javascript">
        if(!+[1,]){ /* 新增判断:如果是IE浏览器,则使用table兼容方式 */
            Render = "table";
        } else {
            Render = "canvas";
        }
        $('#qr-img').qrcode({width:150,height:150,render:Render,correctLevel:0,text:window.location.href});  
    </script>
<?php } ?>

每个<li>代表一个按钮,上下位置自行按需调整即可。全部完成之后,彻底刷新各种缓存,就能看到前文贴图一样的效果了!其他主题只需参考折腾即可。

Tips: 上述代码也未加入中文兼容,如有需求,只需要继续增加兼容中文的 js 代码,然后把 content = window.location.href; 改成 content = utf16to8(window.location.href); 即可搞定。

六、兼容方案

前几天,鸟哥反馈我博客在 IE8 会导致整个浏览器卡死的问题!我苦逼定位了 2 个多小时才搞定!

定位方法非常苦逼:

①、先移除所有 JS,测试依然卡 B ②、移除 wp_footer()输出,测试依然卡 B ③、移除 wp_header()输出,好了!!

尼玛,发现问题出现在头部输出里面,于是分别开启和关闭头部输出,得出头部输出内容,然后一项一项添加上去看是否会卡 B。

最终,发现居然是一个我自定义的 CSS 代码导致的???原来是一个 CSS 属性的大括号被我写成了中文符号,真是 R 了狗了。。。

在测试中,我发现 IE 下无法生成二维码,于是脑补了下,发现 IE 不支持 canvas 模式,只支持 table 模式。

因此多写一个判断搞定:

<script type="text/javascript">
if(!+[1,]){ /* 新增判断:如果是IE浏览器,则使用table兼容方式 */
     Render = "table";
} else {
     Render = "canvas";
}
$('#qr-img').qrcode({width:150,height:150,render:Render,correctLevel:0,text:window.location.href}); 
</script>

Ps:没错,这也是史上最短的 IE 判断,大家可以记录下,以备后用。

等使用 table 模式后,发现生成的二维码惨不忍睹,而且还扫不了:

后来和鸟哥交流的时候,他说是这主题 table 样式有冲突,重新下指定下二维码的 table 属性即可:

PHP

<!-- table模式下修复点阵过于分散导致二维码扫描失效问题 --> <style>.qr-img td { border: none;padding: 0;}</style>

其实,table 模式就是黑白表格组合原理,主题定义的表格样式把 qrcode 生成的二维码搞成了鬼样。

Ps:此项修复已加入到上一步 Begin 代码中,其他主题请自行参考。

七、对比分析

本文介绍的二维码是每个页面动态生成的二维码,扫码后打开的也是当前页面,但是不管是静态还是动态,图片加载的方式总是要产生一个 http 请求的,当页面处于海量访问时就会带来一定的负载了。。。

但是,如果使用 js 生成二维码的方式,这图片就在前台浏览器生成的了。抛开 JS 的兼容性不说,在海量请求场景应该可以极大的减少 http 请求量吧?

当然,JS 生成方式需要多载入一个 Jquery.qrcode.min(通用 JQ 一般都有,就不算了)。看了下,这个 JS 只有 13KB:

而且,我们完全可以把他合并到其他 JS 当中,那就连 http 请求都省了!可见,换成 JS 方式的性价比还是比较可观的!当然,JS 的兼容性就另说了,这里就不多说了,感兴趣的可以试试。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 分享WordPress显示评论者IP的归属地及运营商信息的2种方案

    张戈博客之前分享过一篇《WordPress 显示访客 UA 信息:Show UserAgent 纯代码轻度汉化版》的部署教程,算是满足了 WordPress 折...

    张戈
  • PHP7.0正式版编译安装升级及WordPress问题解决分享

    盼望以久的 PHP 7.0 正式版,终于在今天发布了! ? 官方给出的新特性如下: PHP 7.0.0 comes with new version of th...

    张戈
  • WordPress发布文章自动同步到新浪微博(带特色图片)

    WordPress 发博客后自动同步到新浪微博,这是我从无主题博客看到的方法,一直沿用至今。感觉对博客宣传和提升“逼格”都有显著的作用: ? 一、老版代码 先来...

    张戈
  • ExtJs学习笔记(21)-使用XTemplate结合WCF显示数据

    个人认为,XTemplate是ExtJs中最灵活的用来显示数据的组件,有点类似aspx中的Repeater控件,显示数据的模板完全可以由用户以html方式来定制...

    菩提树下的杨过
  • 从混沌到有序的远程办公进阶之路

    抗击疫情,腾讯云在行动。为保证疫情之下员工的安全,国内启动了有史以来最大规模的远程办公。由于来的突然,很多企业和个人无论是从心态还是基础设施层面都没有做好远程办...

    用户7118204
  • 有了OpenDaylight,我们还需要ONOS吗?

    这又是一道新的选择题。 当然,这样的选择题充斥着整个电信行业从辉煌走向衰落的全过程,那就是标准之争:有了标准就有了一切,输掉了标准就输掉了整个产业。 在传统的I...

    SDNLAB
  • SpringBoot基础篇AOP之高级使用技能

    前面一文,主要介绍的是根据正则表达式来拦截对应的方法,接下来演示下如何通过注解的方式来拦截目标方法,实现也比较简单

    一灰灰blog
  • Autojs豆瓣小组自动回帖机器人,模拟器可用

    有小组回帖和顶自己发的帖两个app,免费使用;给定名是区分用户的,不然这么多人一起用服务器就乱套了!

    小锋学长
  • 怎么用wait、notify巧妙的设计一个Future模式?

    我们知道多线程可以实现同时执行多个任务(只是看起来是同时,其实是CPU的时间片切换特别快我们没感觉而已)。

    烟雨星空
  • 为什么你的原型总是改?

    每个需求产生到以产品的形态呈现大致要走上图的几个步骤,需求的获取、需求的分析前面的文章已经写过怎么做了,这篇主要分享业务流程怎么做,有经验的小伙伴应该都组织或参...

    靠谱先生

扫码关注云+社区

领取腾讯云代金券