article poster 09/22/2020
最近更新于:

分享功能

以前浏览别的博主网站的时候总会在文章页末看到或多或少一些分享功能,比较常见的都是些社交平台的按钮,当时想的是功能虽好可有多少人会去用啊?心想嘛就是个摆设还不如不要占位置233

后来呢又看到了很多优秀主题都自带分享功能,主要是做的美观!这个是重点hhh,然后自己也试了下感觉是挺方便(不管有没有人用,但功能还得有,能极大程度提升用户交互性嘛)当然了就凭上面的那些因素还是不足以构成去做一个功能的需求的感觉,,直到我看到了一个海报生成功能,茅塞顿开想起这玩意很多领域都在用,尤其是之前做过的小程序都会涉及到一个东西,二维码。

海报生成思路

还是先说下实现思路,利用 qrcode.js 生成二维码链接,再使用 html2canvas 将指定元素(含标题、内容、图片、二维码等信息)生成为图片即可。思路很简单实现起来也不难,不过还是有些踩过的坑需要记一下。

海报生成效果图

页面二维码

以上,生成二维码我也上网搜了下,有现成API可以用(网上可以搜到)缺点是速度慢不能及时响应操作,另外就是这次要使用的 qrcode.js

qrcode.js

QRCode.js 项目地址: davidshimjs/qrcodejs

首先在官网下载并引入 qrcode.js(无依赖项)

    <script src="https://cdn.jsdelivr.net/npm/davidshimjs-qrcodejs@0.0.2/qrcode.js"></script>

配置 qrcode.js(创建一个 id 为 qrcode 的元素)

var qrcode = new QRCode(document.getElementById("qrcode"), {
  text: "http://jindo.dev.naver.com/collie",  //二维码链接title
  width: 128,  //宽度
  height: 128,  //高度
  colorDark : "#000000",  //颜色
  colorLight : "#ffffff",  //背景
  correctLevel : QRCode.CorrectLevel.H  //识别程度(H/M/L)
});

//配置完成后你还可以使用方法快速创建/删除一个新的二维码链接()
qrcode.clear(); // clear the code.
qrcode.makeCode("http://naver.com"); // make another code.

海报的生成

完成以上二维码配置后,只需要将当前 url(location.href) 代入其中即可生成当前二维码链接到指定元素内,接着就是笔记的重点

html2canvas

html2canvas 项目地址: niklasvh/html2canvas

见如其名 html to canvas 就是将 html 渲染成 canvas 图片呗,对就这么个意思(不纠结实现原理是咋样的 html2canvas 是通过类似“屏幕截图”的方式将指定元素截图后生成 canvas 图片,其截图位置在文档左上角)知道它可以帮我们生成图片就行了,然后是相关配置项,同样的引入 html2canvas.js

    <script src="http://html2canvas.hertzen.com/dist/html2canvas.js"></script>

然后是调用代码(创建一个 id 为 capture 的元素)

html2canvas(document.querySelector("#capture")).then(canvas => {
    document.body.appendChild(canvas)
});

问题修复

然而 html2canvas 使用并没有想象中那么顺利,期间出现过很多问题,包括需要了解其部分实现原理才能解决,下面简单列一些

图片跨域

图片生成后发现图片不显示,控制台报 CORS 错误,原因在 html2canvas/documentation 文档中有的配置项,其实有关于 CORS(useCORS/allowTaint) 跨域的选项,不过默认都是 false 所以我们在初始化 js 的时候需要添加需要的配置项

html2canvas(document.querySelector("#capture"),{
    useCORS: true,
    allowTaint: true
}).then(canvas => {
    //..
});

图片透明

图片生成后发现图片不透明,原因是其 base64 链接格式不是 png 格式,同样的在配置项中有 background 可选项,只可以是任意 Hex 色值或 null(设置 null 为透明背景,早期版本可设置其值为 "transparent")

html2canvas(document.querySelector("#capture"),{
    backgroundColor: null  //"transparent" 同样适用
}).then(canvas => {
    //..
});

图片模糊

这个问题很多人遇到过,保存的图片没问题但显示图片模糊,直接原因就是使用了 transform 的位置偏移属性,不过配置项里是有一个 scrollX/scrollY 的配置项的,我们之间将其加入配置项并设置值为 0

html2canvas(document.querySelector("#capture"),{
    scrollX: 0,
    scrollY: 0
}).then(canvas => {
    //..
});

还没完,刚开始设置后就没问题了,不过后期我又发现图片开始迷糊了。。为了修复这个问题我们前面提到 html2canvas 基本原理有讲到它是从文档左上角开始截图的,也就是说保证被截图元素(#capture)最好是在文档左上角并无位置偏移,要实现这个我们需要使用到 fixed 将 #capture 元素固定到文档左上角即可(事实证明还是没能完全避免图片模糊的情况,不过可以大幅度缓解模糊幅度)

#capture{
    position: fixed;
    top:  0;
    left: 0;
    z-index: -9;  /*隐藏被截图元素,注意不能设置 display: none 或 visibility: hidden 否则会无法或生成空白图片*/
}

Canvas to Base64

没错,因为 html2canvas 默认只渲染了 canvas 图片,而 base64 链接会好很多(可直接作为 src 存于 img 标签便于操作)所以我们需要在生成 canvas 时将其转为 base64 链接并写入图片元素

canvas 已经提供了 toDataURL api 我们之间调用就可以了

html2canvas(document.querySelector("#capture"),{
    useCORS: true,  //跨域资源共享
    allowTaint: true,  //跨域服务器资源共享
    backgroundColor: null  //透明背景
    scrollX: 0,  //X轴偏移修复
    scrollY: 0  //Y轴偏移修复
}).then(canvas => {
    //canvas 转 base64 图片链接
    let baseUrl = canvas.toDataURL("image/png"),
        imgDom = '<img src="'+baseUrl+'" />';
    document.getElementById('capture').innerHTML += imgDom
})

简单总结

利用 qrcode.js 和 html2canvas 及以上配置完成后,即可生成包含指定链接二维码的海报图(每个需求不一样实现的方式也不同,所以了解实现的操作就可以做自定义的东西了)可以点下面第 4 个分享按钮测试(也可以右键查看生成的海报元素结构)


以上,有问题评论区留言。