前端程序员墓志铭:永远不要使用Alpha版的插件
最近写一个活动项目需要将一个HTML页面转为图片,之前一直是后台采用拼接的方式完成,然而现在遇到一个问题,Java拼接的HTML在生成图片时由于里面的文字太长没法自动换行,想使用css的强制换行
#wrap{word-break:break-all; width:200px;}
或者
#wrap{word-wrap:break-word; width:200px;}
<div id="wrap">abcdefghijklmnabcdefghijklmnabcdefghijklmn111111111</div>
均没有实现想要的换行效果,不知道有没有哪位朋友遇到过类似的情况,欢迎分享一下.
总之我使用css是没有走通,于是选择使用html2canvas.js这个插件在前端生成图片.
在介绍这个插件前先科普一下软件的版本号.
Alpha:是内部测试版,一般不向外部发布,会有很多Bug.一般只有测试人员使用。
Beta:也是测试版,这个阶段的版本会一直加入新的功能。在Alpha版之后推出。
α、β、λ常用来表示软件测试过程中的三个阶段,α是第一阶段,一般只供内部测试使用;β是第二个阶段,已经消除了软件中大部分的不完善之处,但仍有可能还存在缺陷和漏洞,一般只提供给特定的用户群来测试使用;λ是第三个阶段,此时产品已经相当成熟,只需在个别地方再做进一步的优化处理即可上市发行。
这款插件最坑的地方就是将Alpha
版放了出来,而我刚好就选择了最新的版本
以后使用插件就应该看官网demo引入哪个版本的插件我们就使用哪个,要不这坑进去了真的很难出来.
行了,废话不多说了,直接进入正题
使用哪种语法
首先我们整体了解一下html2canvas.js这个插件,大家可以到官网上查阅文档
http://html2canvas.hertzen.com/documentation.html
或者参阅这篇文章
http://www.jianshu.com/p/6a07e974a7e8
引入html2canvas.js文件,我这里使用的是0.4.1
版本(从1.0
版降下来的),
上面两个链接分别对应两种语法格式
html2canvas(document.getElementById('id'))
.then(function(canvas) {document.body.appendChild(canvas);});
但是我在使用这种语法报错,然后参考官网的文档写法
html2canvas(document.getElementById("target"), {
allowTaint: true, //允许污染
taintTest: true, //在渲染前测试图片(没整明白有啥用)
useCORS: true, //使用跨域(当allowTaint为true时这段代码没什么用,下面解释)
background: "#fff",
onrendered: function (canvas) {
imgBlob = canvas.toDataURL('image/jpeg', 1.0); //将图片转为base64
imgBlob = imgBlob.toString().substring(imgBlob.indexOf(",") + 1);//截取base64以便上传
}
});
有关允许canvas污染
的问题可以参考此文
https://developer.mozilla.org/zh-CN/docs/Web/HTML/CORS_enabled_image
其实这里的代码很好理解,传参数进去,剩下的就交给插件去完成,我们只要拿到base64流就可以了.
上文中说useCORS
没有起作用我们看看源码就明白为什么没起作用了
...
} else if ( isSameOrigin( src ) || options.allowTaint === true ) {
...
} else if ( supportCORS && !options.allowTaint && options.useCORS ) {
...
};
...
这里我们看到这两个判断是互相矛盾的options.allowTaint
为true那么!options.allowTaint
永远为false
allowTaint
该设置成true还是false
点击查看
因为allowTaint
表示是否允许被污染,而被污染的canvas是没法使用toDataURL()
转base64
流的,但是我们这需要base64
,所有allowTaint
需要被设置为false
当设置为true时,会报这样的错误
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
at Object.onrendered (http://127.0.0.1:8080/:142:32)
at Object.options.complete (http://127.0.0.1:8080/js/html2canvas.js:2711:15)
at start (http://127.0.0.1:8080/js/html2canvas.js:2215:17)
at Image.img.onload (http://127.0.0.1:8080/js/html2canvas.js:2352:7)
useCORS
是干嘛的
当useCORS
为false
时我们发现
这是什么鬼?图片去哪了?不过已经有突破了,图片出来了,现在我们需要找到图片不加载的问题
我们把
useCORS
设置成true时是什么效果呢?然鹅效果还是和上图一样,但是这次控制台出现了错误
Access to Image at 'http://web.rrzuzu.com/WebStatic/rry-activity/target/images/bj.jpg' from origin 'http://127.0.0.1:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1:8080' is therefore not allowed access.
...
由于公司里面将图片资源放在OSS里,这里涉及到跨域的问题造成图片没法加载,好了,找到问题的所在我们就能很快的解决了,将资源放到同一域名下(OSS设置允许跨域不知道能不能解决,后期会再次尝试一下)
再来看看解决后的效果
哈哈,大功告成!
哦,对了,关于布局的坑我还得提议下
布局
布局一开始想到的是使用display: none
让元素隐藏,当使用这种方法后发现生成的什么也没有.
没办法,使用position: absolute
让元素跑到视野之外总行了吧top: -9999px
;
纳尼,一片漆黑,查了些资料发现生成视野内图片,那么top: 9999px
行不行?事实证明是可以的,这样设置总感觉心理不踏实,万一body
的高度为100000px
怎么办?接着有尝试使用left和right,均没什么卵用,这时想到使用图层高度,OK,那就试试吧,top: 0px; z-index: -1;
完美解决
等等,我们现在只是在模拟器里面测试,还没有在真机上测试,当在真机上看到的效果时我的内心是崩溃的,手机不支持overflow: hidden;
属性WTF,还得想办法此时查到了一些资料:
禁止蒙层底部页面跟随滚动http://mp.weixin.qq.com/s/704rUV3U0BwQuVea1Iwe4Q
最简单的方法时使用position: fixed;
这方法很好,解决了下层页面没被隐藏和软键盘弹出后页面的问题,然而生成的图片没法显示,依旧是一片漆黑,总之试了很多次,只要在body
使用fixed
就别想生成图片,最后发现只用css是没法实现的了,于是结合js一起操作
最后使用fixed
操作同级的container
让其在软件盘弹出或消失的时候始终将元素保持bottom: 0;
,再让页面没法滚动
$('.container')[0].addEventListener('touchmove', e => {
e.preventDefault()
}, false)
总结一句需要生成的元素得在fixed
的上层,并且不能让页面滚动
至此,功能算是完成了,改踩的坑也踩得差不多了,以后遇到问题再继续更新
小插曲
当时我在生成图片的时候获取了返回的图片地址,但是有时候服务器并没有返回图片地址,而我需要将图片地址传递到另外的一个页面,所以需要判断一下,在有地址的时候再执行ajax传递并跳转
success: function (res) {
imgUrl = res;
//提交表单
if (imgUrl) {
$(".form").ajaxSubmit({
...
success: function (data) {
if (data.code == 12000) {
debugger;
window.location.href = "http://wx.pingpingapp.com/activitymanage/pic#" + imgUrl;
}
}
});
}
}
如果有朋友对html2canvas.js
有兴趣,想查看我的项目源码的可以到github上拉取,如果大家对此插件有更深刻的理解欢迎留言
最后再多说一句:人人摇是个啥?扫码你就知道啦