html2canvas 生成图片踩坑记

本次作h5 活动,遇到一个需求,点击button 把html 生成图片,长按保存功能 因为html的结构比较复杂,使用canvas 直接画相对来讲增长了不小工做量,因此使用html2canvas ,html2canvas的使用比较简单,可是坑也不少css

老生常谈的跨域问题

谈到跨域问题,应该只要入了canvas toDataURL 转成图片的坑就应该遇到过这个问题,若是不进行跨域处理生成图片不能跨域的图片会空白处理 这个没有好的解决方案, 图片服务器须要配置Access-Control-Allow-Origin 因为公司的开发build 与 js 是两个团队在作,build 团队的图片地址都是不可跨域的,并且页面因此的图片设置都是background image 的形式,针对这个问题我作了以下处理html

  1. 把以前build 图片下载从新上传到支持跨域的cnd 服务器
  2. 把须要生成图片的html css 样式背景图片进行重写

固然这样尚未结束,配置html2canvasvue

html2canvas(dom, {
        backgroundColor: null,
        canvas,
        //allowTaint: true,
        useCORS: true
    })
复制代码

useCORS 设置容许跨域,特别提醒 allowTaint 也是容许跨域,可是这个容许跨域只是容许你跨域生成canvas ,可是仍是不能把canvas转化成图片,要想解决toDataURL 的跨域问题,还须要使用useCORS。可是这两个属性不能共生web

生成的图片模糊

把scale 设置成二倍直接上代码算法

* 根据window.devicePixelRatio获取像素比
 */
function DPR() {
    if (window.devicePixelRatio && window.devicePixelRatio > 1) {
        return window.devicePixelRatio;
    }
    return 1;
}

.....

  // DOM 节点计算后宽高
    const width = parseValue(box.width);
    const height = parseValue(box.height);
    // 获取像素比
    const scaleBy = DPR()*2;
    // 建立自定义 canvas 元素
    var canvas = document.createElement('canvas');
    // 设定 canvas 元素属性宽高为 DOM 节点宽高 * 像素比
    canvas.width = width * scaleBy;
    canvas.height = height * scaleBy;
    // 设定 canvas css宽高为 DOM 节点宽高
    canvas.style.width = `${width}px`;
    canvas.style.height = `${height}px`;
     // 获取画笔
    const context = canvas.getContext('2d');

    // 将全部绘制内容放大像素比倍
    context.scale(scaleBy, scaleBy);
    // imageSmoothingEnabled Canvas 2D API 用来设置图片是否平滑的属性,true表示图片平滑(默认值),false表示图片不平滑,默认的改变大小的算法会形成图片模糊而且破坏图片原有的像素。 若是那样的话,设置属性值为false。
    context.mozImageSmoothingEnabled = false;
    context.webkitImageSmoothingEnabled = false;
    context.msImageSmoothingEnabled = false;
    context.imageSmoothingEnabled = false;
.....

html2canvas(dom, {
        backgroundColor: null,
        canvas,
        width: width, // 设置width
        height: height, // 设置height
        scale: scaleBy,// 设置scaleBy
        useCORS: true
    })
复制代码

过程当中使用的雪碧图最容易出现模糊的状况,因此图片须要使用2倍图canvas

生成图片过程当中会出现html闪现

可能这个题目不是很好的描述问题。我先描述一下问题所在,因为html2canvas 生成图片所在的html 必须是真实存在的,不然生成canvas为空白。也就是须要生成html不能设置 disabled: none; visibility: hidden; 等属性。 所以代表在调用html2canvas 生成canvas 过程当中必须dom 节点渲染完成。所以这就会致使在生成canvas 会出现原有html 的闪现 这个问题其实也比较好解决,用了一个小技巧,使用top 属性,把html 移除视野 top:100% 固然这个解决方案比较多,目前我用的是这个跨域

动态渲染html 生成canvas会出现样式错乱

这个问题,自己须要生成的html 中有一部分是轮播图,这样html dom 会动态渲染, 解决方案很简单,取消轮播图,直接用 v-if(注:工程使用vue 开发)断定进行html 渲染,取消轮播bash

生成的图片background-repeat: no-repeat;不生效,致使图片重复

这个问题我也没找到缘由,结果就是虽然设置了background-repeat: no-repeat; 可是图片底部会出现大约1像素的重复。 因为没有找到根本缘由,使用了最直接的的方案解决,直接把图片高度增长2像素,成功避免了这个问题。(哈哈哈哈,我真是一个投机取巧的鬼才)服务器

html2canvas 不支持 display: -webkit-box

因为代码中有段文字须要多行末尾省略号,因此出现以下cssdom

display: -webkit-box;
    overflow: hidden;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    text-overflow: ellipsis;
复制代码

在html2canvas中,会将css中的display中的值映射成一个数字,而在下图的映射表中,只要找到了flex的映射值,并无--webkit-flex的映射值,因此-webkit-flex被映射成了DISPLAY.NONE,从而致使了isVisible的计算值返回了false,最终致使了没法生成想要的canvas

解决方案不使用flex布局,js 实现文字溢出,此方案仅限于文字个数具体的状况下,因此比较局限,你们有好的方案欢迎补充 css

height:2倍的line-height; /*根据实际需求更改*/ 
display:inline-block;
复制代码

js

contentText(num){
        const ellipsis = oldContentText.length > num?'...':''
        return oldContentText.slice(0,num) + ellipsis
  }
复制代码
相关文章
相关标签/搜索