上午突然想到给网站文章加一个生成海报的功能,由于后台是PHP,前台是wp,就先度娘了一波:“wp如何生成海报”,发现网上有一堆插件,哈哈哈,真棒。

然后我灵机一动,是否前端也能实现这样的功能?没想到,我的周四一天就这样过去了。。。

插件一:html2canvas

整理了一些思路就开始了第一个插件的尝试:
由于之前听说过html2canvas,想到的第一种方法就是它,通过canvas造图片,然后点击图片再下载。

然后开始写静态页面:

<style type="text/css">body{background:#f5f5f5} 
.canvas-box{position:relative;height:auto;width:300px;filter:drop-shadow(0 2px 10px rgba(0,0,0,.15))}
#canvas{width:300px;height:420px;background:#fff;position:absolute;z-index:1;left:0;top:0;border-radius:10px 10px 0 0px;overflow:hidden}
.canvasImg{width:100%;height:210px}
#canvas h3{padding:0 20px;margin:5px 0;height:90px;overflow:hidden;font-size:20px;font-weight:600;line-height:1.6}
#canvas p{width:100%;height:36px;color:#fff;text-transform:uppercase;background:rgba(255,255,255,.2);line-height:36px;padding:0 20px;position:absolute;z-index:2;left:0;top:160px}
#qrcode{width:80px;height:80px;position:absolute;right:0;bottom:0px;border:10px solid #f7f8fb;border-radius:0;z-index:1}
.canvasLogo{max-width:120px;height:auto;max-height:60px;position:absolute;z-index:2;left:20px;top:340px}
#saveImg{width:300px;height:420px;border-radius:10px 10px 0 0px;overflow:hidden;position:absolute;z-index:2;left:0;top:0}
.saveImgMsg{width:300px;height:40px;padding-top:10px;font-size:14px;color:#999;border-radius:5px 5px 50% 50%;line-height:40px;text-align:center;position:absolute;z-index:1;left:0;top:410px;background:#f6f6fc}
</style>
<div class="canvas-box">
<div id="canvas">
<img class="canvasImg" src="../img/z.png" alt="" />
<h3>测试标题标题标题标题标题标题标题标题标题标题标标题标题标题标题标题</h3>
<p>https://www.baidu.com</p>
<div id="qrcode"></div>
<img class="canvasLogo" src="../img/logo.png" alt="" />
</div>
<img id="saveImg" src="" alt="" />
<p class="saveImgMsg">点击图片,立即下载</p>
</div>

然后就是用js和插件实现这个功能:

<script src="../js/jquery.qrcode.js" type="text/javascript" charset="utf-8"></script>
<script src="../js/html2canva.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
$(function() {
let urls = window.location.href;
let saveImg = document.getElementById("saveImg");
CreatCode(urls); //生成二维码
function CreatCode(a) {
if(a) {
$('#qrcode').qrcode({
width: 80,
height: 80,
text: a
});
}
}
 

var canvas = document.getElementById("canvas"); //获取dom
var width = canvas.offsetWidth; //dom宽
var height = canvas.offsetHeight; //dom高
html2canvas(canvas, {
scale: 2, //缩放比例,默认为1
allowTaint: true, //是否允许跨域图像污染画布
useCORS: true, //是否尝试使用CORS从服务器加载图像
width: width, //画布的宽度
height: height, //画布的高度
}).then((canvas) => {
//将canvas转为base64格式
var imgUri = canvas.toDataURL("image/png"); //图片格式
console.log(imgUri)
$("#saveImg").attr("src", imgUri);
// 把url放到我们的a标签中,并得到a标签对象

});
let flag = false;
$("#saveImg").click(function() {
alert(123)
if(!flag) {
var link = document.createElement('a');
link.href = $("#saveImg").attr("src");
link.download = 'canvas.png';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
flag = true;
return flag;
} else {
alert("您已下载,快去分享吧!")
}
})
})
</script>

写完之后,本地测试完美,点击确实能生成图片,效果很棒,开心我差点飞起来,被后端搞一天的功能,前端一会儿就实现了,然后扔到服务器上,嵌套php程序,发现一直出现“白屏”,Why?发生了什么?

<div class="qui-boom canvas-baner hide">
                             <div class="qui-boom-close"></div>
                            <div class="qui-boom-center canvas-box">
                            <div id="canvas">
                        <img class="canvasImg" src="<?php echo get_content_first_image(get_the_content()); ?>" crossorigin="anonymous" alt="" />
                        <h3><?php the_title(); ?></h3>
                        <p><?php bloginfo('url'); ?></p>
                        <div id="qrcode"></div>
                        <img class="canvasLogo" src="<?php echo get_option("logo_img") ?>" crossorigin="anonymous" alt="" />
                        </div>
                            <p class="saveImgMsg hand">点击图片,立即下载</p>
</div></div></div>

看到有人说这个插件需要在服务器端加入请求头:Access-Control-Allow-Origin: *  ,然后服务器加入之后重启发现依旧是“白屏”。

然后我就怀疑是不是我写法有问题?为什么本地都可以,服务器上就不行了呢?接着折腾,将canvas的盒子复制一份,放到页面中,继续测试,还是“白屏”,疯了。。。 然后发现一篇文章说:页面中被滚动出屏幕的部分,加载不到,所以“白屏”。
我就不得不将事件放到了p元素上,点击p,然后再调用html2canvas生成海报,结果,事实证明绘制区域正常显示也不能绘制出图片,还是“白屏”。

仔细看了一下代码,有可能是弹框的隐藏导致了绘制失败!!!
然后继续度娘,找类似原因:html2canvas为什么会白屏?

最后发现这个插件有很多不兼容、bug造成白屏:背景混合模式,边框图像,盒子装饰断裂,盒子阴影,过滤,字体变体连字,混合混合模式,对象拟合,重复线性梯度、写作模式、缩放。

然后在bug反馈页面(https://github.com/niklasvh/html2canvas/issues/493)发现了同款插件
dom-to-image,先收藏,再给html2canvas一次机会。继续修改布局,去掉弹框,扔页面里面,我日啊,最后我把投影,过滤属性,缩放都改了,发现依旧是“白屏”。。。

算了,彻底放弃,去用下同款插件吧!不得不放弃了这个插件,可能这个插件不能用在 弹框内!

插件二:dom-to-image

打开插件网站,发现教程很详细,真香!直接复制代码到我们写好的事件里面:

$(".saveImgMsg").click(function() {
if(!flag) {  
        domtoimage.toBlob(document.getElementById('canvas')).then(function (blob) {
                   window.saveAs(blob, 'share.png');
        }); 
return flag;
}
})

引入js和插件,刷新页面,窝草,直接可以用了。。。

真是醉了,浪费一天去测试一个插件,发现最后成功的是比它弱的小插件,太戏剧了。

效果预览,点击文章详情下面的“分享”,就可以体验了。

插件地址:

html2canvas:https://github.com/niklasvh/html2canvas/
dom-to-image:https://www.npmjs.com/package/dom-to-image
FileSaver:https://github.com/eligrey/FileSaver.js/