html2canvas踩坑记

前端程序员墓志铭:永远不要使用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
点击查看

因为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是干嘛的

useCORSfalse时我们发现
看到了希望
这是什么鬼?图片去哪了?不过已经有突破了,图片出来了,现在我们需要找到图片不加载的问题
我们把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;
image.png

纳尼,一片漆黑,查了些资料发现生成视野内图片,那么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上拉取,如果大家对此插件有更深刻的理解欢迎留言

最后再多说一句:人人摇是个啥?扫码你就知道啦

猜你喜欢

转载自blog.csdn.net/coding_1/article/details/79015042