前面的话
在电脑端发现一篇好的博文,想在手机上访问。这时,就必须打开手机浏览器输入长长的URL地址才行,非常不方便。如果在博客标题的后面跟一张小的图片,点击该图片后,出现一张二维码的大图,然后再通过手机扫一扫,来进行博文的访问,就相对方便很多。
通过搜索引擎搜索了一些生成二维码的文章,发现其并不是一件容易的事。同时,也发现了qrcode插件,该插件专门用于生成二维码。于是,在qrcode的基础上,实现了一个二维码插件qr
效果演示
如果细心的话,会发现该博文标题的后面紧跟着一个表示二维码的手机小图标。点击该图标后,出现二维码大图,通过手机扫一扫,即可进行手机端对网页的访问。再点击小图标或二维码图片后,二维码图片消失
我将该插件命名为qr.js,使用方式很简单,只要进行如下引入既可
<script src="http://files.cnblogs.com/files/xiaohuochai/qr.js"></script>
原理说明
1、首先分析博客园的HTML结构
由上图可知,博客园的博文位于类名为‘post‘的div中,外层是id名为‘topics‘的div,而博文的标题位于类名为‘postTitle‘的h1中。所以,当页面结构加载完成后,就可以在该标题的后面添加图片了
var oBox = document.getElementById(‘topics‘); var oTitle = oBox.getElementsByTagName(‘h1‘)[0]; console.log(oTitle.innerHTML);
2、二维码小图生成
现在,需要准备一个二维码小图,插入博文标题后面
通过iconfont,找到一个二维码小图,该小图如下所示,因为是为了方便移动端使用,所以使用了一个表示‘小手机’的图标
然后将对该图片进行base64编码
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAoklEQVQ4T+2T4Q2CMBCFv27CBjgCG+gIjAAbOAIjOIJs4Ai6gRvIBpjXXCOp19T/8pJLoTneXcj3Ah91wAV4bu68xwXoAZ2EzEAmE9AWTB6AelRDyaAx9zgh0wE4ATczcTdIE7wl0oe7wX/8RMHigfQTB3fDdM1IEvYyONdIVEOSqDwCY2Z2NaS/UNbqMSQmvauUPlfbNKpBSdTUVyXSs/XyBlRCNBG20I28AAAAAElFTkSuQmCC
通过查看样式,使用的皮肤对img标题设置了margin属性,如下所示
所以,这里需要对margin置0
var oBox = document.getElementById(‘topics‘); var oTitle = oBox.getElementsByTagName(‘h1‘)[0]; var oImg = new Image(); oImg.id = ‘oImg‘; oImg.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAoklEQVQ4T+2T4Q2CMBCFv27CBjgCG+gIjAAbOAIjOIJs4Ai6gRvIBpjXXCOp19T/8pJLoTneXcj3Ah91wAV4bu68xwXoAZ2EzEAmE9AWTB6AelRDyaAx9zgh0wE4ATczcTdIE7wl0oe7wX/8RMHigfQTB3fDdM1IEvYyONdIVEOSqDwCY2Z2NaS/UNbqMSQmvauUPlfbNKpBSdTUVyXSs/XyBlRCNBG20I28AAAAAElFTkSuQmCC"; oImg.style.margin = ‘0‘; oTitle.appendChild(oImg);
3、将该网页的URL转换为二维码
获取URL非常简单,只要使用location对象的href属性即可
接下来,就要使用QRCode插件来实现将URL转换为二维码的功能了,首先先下载qrcodejs插件,然后将博文的URL转换为自定义尺寸的二维码
<div id="qrcode"></div> <script src="http://files.cnblogs.com/files/xiaohuochai/qrcode.min.js"></script> <script type="text/javascript"> var qrcode = new QRCode(document.getElementById("qrcode"), { text: location.href, width: 80, height: 80 }); </script>
生成如下图所示的二维码图片
4、动态生成及鼠标点击事件
由于最终是要封装在一个js文件中的,所以第三步涉及到的HTML结构都需要动态生成
由于生成二维码需要依赖qrcodejs插件,所以只要当该插件加载完毕后,才可以进行后续操作。script标签支持load事件,但不兼容IE8-浏览器。所以,更保险的方法是使用window.onload
鼠标点击标识图片后,在标识图片的右侧显示生成的二维码图片,由于该二维码图片要相当于图片进行绝对定位,所以需要改变HTML结构,在小标识图片的外层添加一层oImgBox的div,用于定位大的二维码图片
//获取博文标题 var oBox = document.getElementById(‘topics‘); var oTitle = oBox.getElementsByTagName(‘h1‘)[0]; //创建标识图片及外层包装div var oImgBox = document.createElement(‘div‘); oImgBox.style.cssText = ‘position:relative;display:inline-block;vertical-align:middle‘; var oImg = new Image(); oImg.id = ‘oImg‘; oImg.style.cursor = ‘pointer‘; oImg.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAoklEQVQ4T+2T4Q2CMBCFv27CBjgCG+gIjAAbOAIjOIJs4Ai6gRvIBpjXXCOp19T/8pJLoTneXcj3Ah91wAV4bu68xwXoAZ2EzEAmE9AWTB6AelRDyaAx9zgh0wE4ATczcTdIE7wl0oe7wX/8RMHigfQTB3fDdM1IEvYyONdIVEOSqDwCY2Z2NaS/UNbqMSQmvauUPlfbNKpBSdTUVyXSs/XyBlRCNBG20I28AAAAAElFTkSuQmCC"; oImg.style.margin = ‘0‘; oImgBox.appendChild(oImg); //将标识图片插入标题后面 oTitle.appendChild(oImgBox); //动态生成script标签,引入qrcode插件 var script = document.createElement("script"); script.type = "text/javascript"; script.src = ‘http://files.cnblogs.com/files/xiaohuochai/qrcode.min.js‘; document.body.appendChild(script); //动态生成div标签,用于放置通过qrcode插件生成的二维码大图,默认隐藏显示 var oDiv = document.createElement(‘div‘); oDiv.id = ‘qrcode‘; oDiv.mark = false; oDiv.style.cssText = ‘display:none;position:absolute;left:20px;top:-40px‘; oImgBox.appendChild(oDiv); window.onload = function(){ new QRCode(oDiv, { text: location.href, width: 80, height: 80 }); } //鼠标移入标识图片外层oImgBox后,在该标识图片的右侧显示二维码图片 oImgBox.onclick = function(){ //如果mark为真,说明二维码图片正在显示,将其隐藏 if(oDiv.mark){ oDiv.style.display = ‘none‘; //否则说明二维码图片正在隐藏,将其显示 }else{ oDiv.style.display = ‘block‘; } //将mark标识置反 oDiv.mark = !oDiv.mark; }
5、移动端优化
由于该功能只适用于电脑端,在移动端并无实际的用处。所以,可以通过用户代理检测,如果是非移动端,才执行上述操作
由于其他的插件也可能会用到window.onload,所以为了避免冲突,使用兼容性的事件处理程序函数
优化后的最终代码如下
(function(){ //事件处理程序兼容写法 function addEvent(target,type,handler){ if(target.addEventListener){ target.addEventListener(type,handler,false); }else{ target.attachEvent(‘on‘+type,function(event){ return handler.call(target,event); }); } } function whichMobile(){ var ua = navigator.userAgent; if(/iPhone OS (\d+_\d+)/.test(ua)){ return ‘iPhone‘ + RegExp.$1.replace("_","."); } if(/iPad.+OS (\d+_\d+)/.test(ua)){ return ‘iPad‘ + RegExp.$1.replace("_",".") } if(/Android (\d+\.\d+)/.test(ua)){ return ‘Android‘ + RegExp["$1"]; } } //如果是非移动端,则执行如下代码 if(!whichMobile()){ //获取博文标题 var oBox = document.getElementById(‘topics‘); var oTitle = oBox.getElementsByTagName(‘h1‘)[0]; //创建标识图片及外层包装div var oImgBox = document.createElement(‘div‘); oImgBox.style.cssText = ‘position:relative;display:inline-block;vertical-align:middle‘; var oImg = new Image(); oImg.id = ‘oImg‘; oImg.style.cursor = ‘pointer‘; oImg.src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAoklEQVQ4T+2T4Q2CMBCFv27CBjgCG+gIjAAbOAIjOIJs4Ai6gRvIBpjXXCOp19T/8pJLoTneXcj3Ah91wAV4bu68xwXoAZ2EzEAmE9AWTB6AelRDyaAx9zgh0wE4ATczcTdIE7wl0oe7wX/8RMHigfQTB3fDdM1IEvYyONdIVEOSqDwCY2Z2NaS/UNbqMSQmvauUPlfbNKpBSdTUVyXSs/XyBlRCNBG20I28AAAAAElFTkSuQmCC"; oImg.style.margin = ‘0‘; oImgBox.appendChild(oImg); //将标识图片插入标题后面 oTitle.appendChild(oImgBox); //动态生成script标签,引入qrcode插件 var script = document.createElement("script"); script.type = "text/javascript"; script.src = ‘http://files.cnblogs.com/files/xiaohuochai/qrcode.min.js‘; document.body.appendChild(script); //动态生成div标签,用于放置通过qrcode插件生成的二维码大图,默认隐藏显示 var oDiv = document.createElement(‘div‘); oDiv.id = ‘qrcode‘; oDiv.mark = false; oDiv.style.cssText = ‘display:none;position:absolute;left:20px;top:-40px‘; oImgBox.appendChild(oDiv); addEvent(window,‘load‘,function(){ new QRCode(oDiv, { text: location.href, width: 80, height: 80 }); }) //鼠标移入标识图片外层oImgBox后,在该标识图片的右侧显示二维码图片 addEvent(oImgBox,‘click‘,function(){ //如果mark为真,说明二维码图片正在显示,将其隐藏 if(oDiv.mark){ oDiv.style.display = ‘none‘; //否则说明二维码图片正在隐藏,将其显示 }else{ oDiv.style.display = ‘block‘; } //将mark标识置反 oDiv.mark = !oDiv.mark; }) } })();