谷歌浏览器插件之二维码识别与生成?拿来吧你!

原创
2022/03/03 09:33
阅读数 3.6K


01

背景

先交代下背景,为什么会有撸个插件的想法呢,起因是公司的协议平台是h5的,首先要打开,在调试不同端项目的时候需要切换协议平台,比如58,安居客,本地版的,有时候要打开好几个页面,而且每个页面我使用的功能基本就是加个协议头,但是我还要把不用的参数一个一个删掉(如果不删的话生成的码非常复杂,不易识别),浪费很多时间,而且还要手动url,很多时候本地调试的时候想生成二维码的url就是当前页面的url,还要复制粘贴过去,再一个有时候协议平台的静态资源还报错,然后就没法用了,插件可以完美的解决我的痛点,并且可以脱机使用,所以就撸了一个插件,文章最后有插件的链接,需要的同学可以自取哈~


01

正文

成品图

按照国际惯例,先放成品图,功能其实很简单,一个是生成二维码(可生成带协议头的二维码),一个是解析二维码,因包含协议等敏感信息,故进行了打码处理

     

目录结构

看一下目录结构,是不是很眼熟,欢迎来到古老的被jquery支配的年代,哈哈开个玩笑,其实一样可以使用框架来开发,全看个人选择,因为使用jquery操作dom比较简单,功能又不是很复杂,所以这次使用了jquery



以本例着重说一下manifest和popup:

manifest:是一个插件配置文件,里面有插件的重要信息,例如插件的名称(必填),版本(必填),图标,权限,匹配路径等等,具体配置请移步谷歌插件官方文档查看(http://chrome.cenchy.com/manifest.html)

popup:是成品图中点击这个icon会弹出的页面,在里面可以写自己想要的功能,跟写html一样,是不是so easy

页面结构

接下来看一下页面结构,非常的平平无奇,主要的逻辑实现在入口js文件中

<html><head>  <meta http-equiv="content-type" content="text/html; charset=utf-8">  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"></head><link rel="stylesheet" href="css/reset.css"><link rel="stylesheet" href="css/style.css"><script src="js/jquery-1.9.1.min.js"></script><!-- 二维码解析库 --><script src="js/jsQR.min.js"></script><!-- 二维码生成库 --><script src="js/qrcode.min.js"></script><!-- 文本复制库 --><script src="js/clipboard.min.js"></script><!-- 主入口文件 --><script src="js/init.js"></script><body id="qr-body">  <div class="wrapper">    <header>      <h1 class="active">生成二维码</h1>      <h1>解析二维码</h1>    </header>    <div class="section-wrap create-wrap">      <div class="input-wraper">        <input id="code-url" type="text">        <div class="create-qr">生成</div>      </div>      <div class="options">        <div class="option-item">          <label for="mode"><span>模式选择:</span>协议模式</label><input class="mode" type="radio" name="mode" value="1"            checked>          <label for="mode">普通模式</label><input class="mode" type="radio" name="mode" value="2">        </div>        <div class="option-item scheme-choose">          <label for="mode"><span>协议选择:</span>58</label><input class="scheme" type="radio" name="scheme" value="58协议头"            checked>          <label for="mode">安居客</label><input class="scheme" type="radio" name="scheme" value="安居客协议头">          <label for="mode">58本地</label><input class="scheme" type="radio" name="scheme" value="58本地协议头">        </div>      </div>      <div class="qr-content">        <div id="qrcode"></div>      </div>      <div class="save-code">        <a class="download" download="qrcode.png" href="">          <p>保存图片</p>        </a>      </div>    </div>    <div class="section-wrap decode-wrap discover">      <div class="decode-result">        <p class="decode-content">解码结果:<span class="decode-str"></span></p>      </div>      <div class="input-section">        <div class="upload-tip">          <img src="img/upload.png">          <p>上传或拖拽二维码图片</p>         </div>        <input id="wait-decode-img" type="file" accept="image/jpg,image/png,image/bmp,image/jpeg"/>      </div>      <div class="copy">        一键复制      </div>    </div>  </div></body></html>

前方有怪兽出没,请注意,如不注意会发生非常可怕的事情

1.页面上的js一定要通过外链脚本的方式引入,不能写内联js,不能写内联js,不能写内联js(此处省略10086遍),否则会不生效,之前我就踩了这个坑,当时还在想是不是我哪里写的有问题

2.在页面中所有的dom操作全是基于当前popup页面的,获取不到当前导航栏地址所在的页面内容,想获取的话会有专门的api去获取,而且有限制,下面会讲到

3.

逻辑实现

看完页面结构该上正菜了,下面就是真正的逻辑实现部分了,准备面对疾风吧,比卡丘!

$(function () {    let qrcode, url, mode = $(".mode").val(),        scheme = $(".scheme").val()
const getQRStr = function () {//根据所选模式获取二维码的字符串,普通模式直接返回输入框内的字符串,协议模式要添加上协议
if (mode == 2)
return url
} else
var params = encodeURIComponent(`{"url":"${url}"}`)
return `${scheme}://xxxx/xxxx/xxxx?params=${params}`;//此处注意,实际使用中请结合协议头请拼接正确的协


const remakeStr = function () {//重新生成二维
qrcode.makeCode(getQRStr())
$(".download").attr("href", $("#qrcode img").attr("src"))//将二维码的链接赋值到保存图片按钮

const decodeQR = function (file) {//解析二维码,接收的是一个file对象,返回的是一个包含解析结果的promise对
return new Promise((resolve, reject) =>
const url = URL.createObjectURL(file),//创建一个URL对象,表示的是传入的file对
img = new Image()
img.onload = function ()
URL.revokeObjectURL(this.src);//释放之前通过URL.createObjectURL()方法创建的对 //因为解析库jsQR需要传入一个imageData对象,所以我们要把传入的file对象转成imageData对象,先通过canvas把image file绘制出来,然后通过getImageData方法拿到imageData对象 var cvs = document.createElement(\'canvas\'); var ctx = cvs.getContext(\'2d\'); cvs.width = this.width; cvs.height = this.height; ctx.drawImage(this, 0, 0); //关于imageData的说明 https://developer.mozilla.org/zh-CN/docs/Web/API/ImageData
const imageData = ctx.getImageData(0, 0, cvs.width, cvs.height);// const result = jsQR(imageData.data, imageData.width, imageData.height); //如果result为true,说明解析成功,反之失败 resolve({ status: result ? true : false, codeStr: result ? result.data : "" }) }; img.src = url; }) } //使用clipboard可以复制传入的字符串 const clipboard = new ClipboardJS(\'.copy\', { text: function (trigger) { return $(".decode-str").text() || null; } });

 //页面插件初始化的时候要拿当前页面的url填入到输入框中,最开始我使用的是location.href,但发现始终拿到的是chrome-extension://keokipipphpaaalmgnoeimafhmbjmped/popup.html,最后查阅文档才发现不能这么拿,这么拿拿到的实际是popup.html的链接,但所幸chrome官方提供了这类api,通过此api可以拿到当前tab页面的一些属性例如url(不要忘记在权限中设置


   
   
   
chrome.tabs.query({        \'active\': true,        lastFocusedWindow: true,        currentWindow: true    }, function (tabs) {        url = new URL(tabs[0].url).toString();//要toString()一下,因为new URL(tabs[0].url)后拿到的不是标准的字符串,生成二维码的时候会报错,血的教训啊= =         $("#code-url").val(url);        qrcode = new QRCode("qrcode", {//初始化生成二维码            text: getQRStr(),//文本字符串            width: 196,//二维码宽度            height: 196,//二维码高度            colorDark: "#000000",//二维码线条颜色            colorLight: "#ffffff",//二维码背景色            correctLevel: QRCode.CorrectLevel.M//二维码等级,等级越高容错率越高,相应的也越复杂,当二维码所描述的文本非常长的时候,质量调的过高容易识别不出来,所以选择了M档        });        setTimeout(function () {            $(".download").attr("href", $("#qrcode img").attr("src"))        }, 1500)    });    $(".mode").change(function () {//模式改变的时候重新绘制二维码        mode = $(this).val();        if (mode == 2) {            $(".scheme-choose").addClass("discover");        } else {            $(".scheme-choose").removeClass("discover");        }        remakeStr();    })    $(".scheme").change(function () {//协议改变的时候重新绘制二维码        scheme = $(this).val();        remakeStr();    })    $(".create-qr").click(function () {//当输入框内容改变的时候只有手动点击生成才会重新生成二维码        url = $("#code-url").val();        remakeStr();    })    $("#wait-decode-img").change(async function (e) {//当上传需要解析的二维码的图片时会解析二维码        const file = e.target.files[0];        const result = await decodeQR(file);        if (result.status) {//如果status是true说明解析成功,将解析出的字符串写到页面上            $(".decode-str").text(result.codeStr);        }    });    $("#qr-body").on("click", "header h1:not(.active)", function () {//解析和生成两个tab的切换逻辑        $(".active").removeClass("active");        $(this).addClass("active");        const discoverDiv = $(".discover");        $(".section-wrap:not(.discover)").addClass("discover");        discoverDiv.removeClass("discover");    })})

安装浏览器插件

到这里一个集识别与生成二维码的浏览器插件就诞生啦,下面讲讲如何安装浏览器插件


然后点击加载已解压的扩展程序就可以使用啦(悄悄的告诉你,直接把已解压的文件夹拖拽到页面上也可以安装),至此大功告成,需要注意的是不要移动插件文件夹所在的位置,这样会造成插件不可用,或者随便改动插件的代码,因为会立即生效,为什么会这样呢,因为我们的插件并没有发到谷歌商店上,这样会被认定为不安全的插件,只能通过类似开发者模式去使用,想要发布到商店的同学要先选择打包,会打包出crx文件和pem秘钥,然后按照商店的指示一步一步的去提交发布信息(友情提示:想要开通谷歌商店的上传资格要6美刀,且只能外币支付哦,有万事达,visa或者运通卡的小伙伴有意向的话可以自行研究,我只开通了账户,但是后续上传审核啥的有点麻烦,就放弃了

赶赶单单吧,一点都不神秘吧,其实浏览器插件能做的有很多很多远不止今天讲的这点,比如background脚本(可以共享导航栏地址所在页面的dom,但是不能共享页面的js哈),鼠标右键的菜单,桌面通知,选项页,覆写特定页等等,今天算是给大家来一点前菜,想吃大餐的话就要靠同学们自己去做了,只要你足够有兴趣,你的浏览器你做主


最后放上链接,有需要的小伙伴自取哦,需要添加协议参数的,可以自己再二次开发,别忘了解压使用    

ps:由于接触时间尚短,难免有疏漏,有错误和建议的地方欢迎指正和交流(不限于插件方面)

链接:

https://wos.58cdn.com.cn/IjGfEdCbIlr/ishare/d35a35d3XdWbV9Wc5a37XU35d1d359Wc.zip

本文分享自微信公众号 - 58技术(architects_58)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部