html2canvas 生成图片踩坑记 您所在的位置:网站首页 canva下载图片模糊 html2canvas 生成图片踩坑记

html2canvas 生成图片踩坑记

2023-12-27 15:03| 来源: 网络整理| 查看: 265

本次做h5 活动,遇到一个需求,点击button 把html 生成图片,长按保存功能 由于html的结构比较复杂,使用canvas 直接画相对来说增加了不小工作量,所以使用html2canvas ,html2canvas的使用比较简单,但是坑也很多

老生常谈的跨域问题

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

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

当然这样还没有结束,配置html2canvas

html2canvas(dom, { backgroundColor: null, canvas, //allowTaint: true, useCORS: true })

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

生成的图片模糊

把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倍图

生成图片过程中会出现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 渲染,取消轮播

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

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

html2canvas 不支持 display: -webkit-box

由于代码中有段文字需要多行末尾省略号,所以出现如下css

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 }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有