html2canvas的踩坑之路

前言

早有耳闻这个html2canvas比较坑,但无奈于产品需求的压迫,必须实现html转图片的功能,自此走上了填坑之路,好在最后的效果还算令人满意,这才没有误了产品上线周期.

html2canvas介绍

html2canvas的详细介绍可以点击这里查看,其实简单来说就是通过canvasHTML生成的DOM节点绘制到画布上,再可以通过自己的需求转换成图片.所以官方文档也说了,最后生成的效果不是100%相同的,这一点大家要有心理准备,无论怎样,一点点小瑕疵是肯定有的。

兼容性

PS:微信浏览器使用也是没有问题的哦

使用html2canvas

使用也是十分简单,官网写的很清楚戳这里

踩坑过程

生成的图片里面为什么缺失微信头像或其他图片?

其实涉及到的就是跨域问题,即便是canvas的画布中对于图片的域也是有要求的,那我们应该怎么解决呢?

  1. html2canvas配置项中配置 allowTaint:true 或 useCORS:true(二者不可共同使用)
  2. img标签增加 crossOrigin='anonymous'
  3. 图片服务器配置Access-Control-Allow-Origin 或使用代理

其中第三步是最重要的,不设置则前两步设置了也无效。

服务器需要配置Access-Control-Allow-Origin信息,如PHP添加响应头信息,*通配符表示允许任意域名:

header("Access-Control-Allow-Origin: *");

或者指定域名:

header("Access-Control-Allow-Origin: www.zhangxinxu.com");

但如果不想麻烦后端的人员,那我们前端怎么跨域呢? 那就可以使用代理插件,如: html2canvas-proxy-nodejs 或者是 superagent,我是使用superagent,贴一下示例代码:

const request = require('superagent') // 导入
const proxHost = 'https://thirdwx.qlogo.cn' // 指定跨域图片的地址
app.use('/proxy', function (req, res, next) {
let urlPath = req.url
console.log('urlPath', urlPath)
urlPath = decodeURI(urlPath)
if (!urlPath) {
console.log('urlPath is null')
return next()
}
console.log('proxy-request: /proxy->' + `${proxHost}${urlPath}`)
const reqStream = request.get(`${proxHost}${urlPath}`)
reqStream.on('error', function (err) {
console.log('error', err)
})
console.log('------reqStream----')
return reqStream.pipe(res)
})

那么最终我在页面中的图片的srchttps://thirdwx.qlogo.cn/xxx 要更改为/proxy/xxx 效果图如下:

2.生成的图片模糊不清且有锯齿瑕疵怎么办?

大部分找到的结果都是使用设备像素比去操作,但实际使用起来,还是会有锯齿。 这个问题苦恼了我很久,并且找了很久的相关资料,总算是功夫不负有心人,让我找到了解决方案,在github里有大神已经提供了解决方案,可以点击这里,大神在源码的基础上增加两个配置项,scaledpi,推荐使用scale参数。

源码位置:https://github.com/eKoopmans/html2canvas/tree/develop/dist

        let imgHeight = window.document.querySelector('.content').offsetHeight // 获取DOM高度
let imgWidth = window.document.querySelector('.content').offsetWidth // 获取DOM宽度
let scale = window.devicePixelRatio // 获取设备像素比
html2canvas(window.document.querySelector('.content'), {
useCORS: true,
scale: scale,
width: imgWidth,
height: imgHeight
}).then((canvas) => {
window.document.querySelector('.content').remove()
let elemImg = `<img src='${canvas.toDataURL('image/png')}' id='canvas-img' style='height: ${imgHeight}px;border-radius: 10px;width:${imgWidth}px'/>`
window.document.querySelector('.container').innerHTML = elemImg
})

最终生成出来的图片,是清晰并且最接近DOM的图片

3.生成的图片中若包含二维码,微信长按图片偶现无法识别?

这个问题主要出现在使用单页面框架(如VUE)的页面. 感谢 sundaypig提出的解决方案。 很简单,就是不使用路由切换,使用window.location.href直接跳转刷新页面

    location.href="www.abc.com/share/xxx"

PS:这个问题可以解决所有页面中偶现二维码无法识别的情况

4.生成的图片中文字间距较大?

这个暂时无法完美解决,可以尝试用css属性:letter-spacing来设置字间距

html2canvas的踩坑之路的更多相关文章

  1. MySQL Connector/NET 使用小结(踩坑之路)

    背景描述 根据项目的需要,需连接MySQL获取数据. 首先,先了解一下项目的情况: 之前的代码是C#编写的的, 运行时:.NETFramework3.5. 由于项目已经部署上线,因此不能升级运行时,这 ...

  2. Android 上传开源项目到 jcenter 实战踩坑之路

    本文微信公众号「AndroidTraveler」首发. 背景 其实 Android 上传开源项目到 jcenter 并不是一件新鲜事,网上也有很多文章. 包括我本人在将开源项目上传到 jcenter ...

  3. Java踩坑之路

    陆陆续续学Java也快一年多了,从开始的一窍不通到现在的初窥门径,我努力过,迷茫过,痛过,乐过,反思过,沉淀过.趁着新年,我希望能把这些东西记下来,就当是我一路走来的脚印. 一.初识网站应用 记得第一 ...

  4. Android SDK 开发——发布使用踩坑之路

    前言 在 Android 开发过程中,有些功能是通用的,或者是多个业务方都需要使用的. 为了统一功能逻辑及避免重复开发,因此将该功能开发成一个 SDK 是相当有必要的. 背景 刚好最近自己遇到了类似需 ...

  5. jQuery升级踩坑之路

    1.使用了被废弃的jQuery.browser属性 jQuery 从 1.9 版开始,移除了 $.browser 和 $.browser.version , 取而代之的是 $.support . 在更 ...

  6. Mahout踩坑之路

    一.版本对比 公司版Mahout 由于Mahout只能允许于hadoop0.20以上版本上,而百度的hadoop是hadoop0.19的一个分支.因此百度HPC组曾经将Mahout移植到百度的hado ...

  7. webpack踩坑之路——构建基本的React+ES6项目

    转自:http://www.cnblogs.com/ghost-xyx/p/5483464.html webpack是最近比较火的构建工具,搭配上同样比较火的ReacJS与ES6(ES2015)一定是 ...

  8. webpack踩坑之路——图片的路径与打包

    转自:http://www.cnblogs.com/ghost-xyx/p/5812902.html 刚开始用webpack的同学很容易掉进图片打包这个坑里,比如打包出来的图片地址不对或者有的图片并不 ...

  9. 踩坑之路_"var name = ' ';"_迷之BUG

    情景介绍:最近写一个拖拽生成图表的工具,自己的思路每次mousedown的时候动态将this的name属性值赋值给全局中变量(自己手贱测试时直接将变量名命名为了'name',一大波bug还有30s到达 ...

随机推荐

  1. CF 317 A. Lengthening Sticks(容斥+组合数学)

    传送门:点我 A. Lengthening Sticks  time limit per test        1 second You are given three sticks with po ...

  2. vue 兼容性——ie家族不支持promise

    解决方案: 安装: cnpm install es6-promise 在 main.js 引入 : polyfill require("es6-promise").polyfill ...

  3. Spring Boot+Quartz实现一个实时管理的定时任务

    转载 https://www.cnblogs.com/wujiwen/p/9615120.html 项目实践过程中碰到一个动态管理定时任务的需求:针对每个人员进行信息的定时更新,具体更新时间可随时调整 ...

  4. stark组件开发之批量操作

    class UserInfoHandler(StartHandler): ....... # 批量操作功能的列表,添加则显示, 使用此功能.需要将StartHandler.display_checkb ...

  5. ps高级磨皮的7个步骤

    1.打开图片 2. 进入通道看红绿蓝哪个通道痘比较明显拖拽复制拷贝哪个通道! 3.选中拷贝的通道--执行滤镜--其他--高反差保留 4.在执行图像--计算(混合模式强光)--计算三次 5.选alpha ...

  6. ScheduledExecutorService--目前最理想的定时任务实现方式

    ScheduledExecutorService 理想的定时任务实现方式 : 通过线程池的方式来执行任务的 可以灵活的设定第一次执行任务延迟时间 提供了良好的约定,以便设定定时执行的间隔时间代码实现: ...

  7. iOS:使用Github托管自己本地的项目代码方式一:(Xcode方式:开发工具Xcode配置Git,由Xcode-->Source Control-->Commit)

    管理代码的地方主要有:Github(国外流行).CocoaChina.Cocoa4App.中国开源社区.CSDN.博客园.简书等等..... 现在主要介绍如何使用Github托管自己的项目代码. 尊重 ...

  8. 【转】linux 查看进程启动路径

    在linux下查看进程大家都会想到用 ps -ef|grep XXX可是看到的不是全路径,怎么看全路径呢?每个进程启动之后在 /proc下面有一个于pid对应的路径例如:ps -ef|grep pyt ...

  9. 2019.02.11 bzoj1568: [JSOI2008]Blue Mary开公司(线段树)

    传送门 题意简述:维护整体加一条线段,求单点极值. 思路: 直接上李超线段树维护即可. 代码: #include<bits/stdc++.h> #define ri register in ...

  10. 根据word模板dotx文件创建word

    doc = this._wordApplication.Documents.Add(@"D:\Fdsfsdsfsdfds.dotx"); 用这个会把模板的样式,文字内容都创建到新w ...