web端
使用 html2canvas
库
html2canvas 能够实现在用户浏览器端直接对整个或部分页面进行截屏。这个html2canvas脚本将当页面渲染成一个Canvas图片,通过读取DOM并将不同的样式应用到这些元素上实现
基本用法
<div id="capture" style="padding: 10px; background: #f5da55">
<h4 style="color: #000; ">Hello world!</h4>
</div>
html2canvas(document.querySelector("#capture")).then(canvas => {
var url = canvas.toDataURL()
document.body.appendChild(canvas)
});
通过调用canvas.toDataURL()
可得到base64
编码的图片地址
注意点
- 生成的图片有空白原因
大多数原因是html的dom元素还没加载完就进行转换图片,最好加上setTimeout延时或者再dom的onload回调函数中处理
- html与转换后图片不一致
html2canvas
没有全部支持css属性,需要取舍
Unsupported CSS properties
These CSS properties are NOT currently supported
- 生成的图片模糊不清且有锯齿瑕疵
设置scale参数
- 设置代理
Proxy
,接口返回图片的base64
编码字符串.例子:node.js ```javascript const express = require(‘express’); const url = require(‘url’); const cors = require(‘cors’); const request = require(‘request’);
function validUrl(req, res, next) {
if (!req.query.url) {
next(new Error(‘No url specified’));
} else if (typeof req.query.url !== ‘string’ || url.parse(req.query.url).host === null) {
next(new Error(Invalid url specified: ${req.query.url}
));
} else {
next();
}
}
module.exports = () => {
const app = express.Router();
app.get(‘/‘, cors(), validUrl, (req, res, next) => {
switch (req.query.responseType) {
case ‘blob’:
req.pipe(request(req.query.url).on(‘error’, next)).pipe(res);
break;
case ‘text’:
default:
request({url: req.query.url, encoding: ‘binary’}, (error, response, body) => {
if (error) {
return next(error);
}
res.send(
data:${response.headers['content-type']};base64,${Buffer.from(
body,
'binary'
).toString('base64')}
);
});
}
});
return app;
};
2. 配置项中配置 `allowTaint:true`, 但不能调用`toDataURL`方法<br />
3. 配置项中配置 `useCORS:true`(与`allowTaint:true`互斥),直接跟文档只添加这个属性是不行的
1、添加useCORS:true属性; 2、给要生成canvas的DOM中包含的每一个标签添加crossorigin=”anonymous”属性;给要生成canvas的dom中的所有标签的src添加一个任意的字符串,只要能起到重新发起图片读取请求,从而避免读取到浏览器缓存数据即可,如:’http://h0.hucdn.com/open/201819/9404b56f97e7df8a_750x1334.png?any_string_is_ok‘ 3、确保你的图片CDN服务器支持CORS访问,也就是会返回Access-Control-Allow-Origin等响应头;需再阿里云CDN后台设置
解释:<br />`useCORS:true`的作用`img.crossOrigin = 'anonymous'` [源码地址](https://github.com/niklasvh/html2canvas/blob/cae44a6f0a6649bd8a7c4250a20792bb5c2e5b42/src/core/cache-storage.ts)
```javascript
const img = new Image();
img.onload = () => resolve(img);
img.onerror = reject;
//ios safari 10.3 taints canvas with data urls unless crossOrigin is set to anonymous
if (isInlineBase64Image(src) || useCORS) {
img.crossOrigin = 'anonymous';
}
img.src = src;
if (img.complete === true) {
// Inline XML images may fail to parse, throwing an Error later on
setTimeout(() => resolve(img), 500);
}
if (this._options.imageTimeout > 0) {
setTimeout(
() => reject(`Timed out (${this._options.imageTimeout}ms) loading image`),
this._options.imageTimeout
);
}
crossorigin=’anonymous’就可以触发带跨域请求头Origin的HTTP请求了,除了请求头要添加Origin之外,服务器的响应头中也必须要包含正确的Access-Control-Allow-Origin才行,否则就说明服务器并不接受客户端的跨域请求
html2canvas库需要我们先提供一段DOM节点,然后它再读取并解析这一段DOM节点生成canvas对象。如果DOM节点中已经使用了标签的话,它也会解析这个标签的src属性,然后重新创建一个Image对象,给它添加crossOrigin=”anonymous”属性后尝试以跨域的方式重新读取图片数据。需要注意的是,一般CDN上的图片都是带有缓存响应头并且会在浏览器端缓存的,而且缓存的不仅仅是图片数据,还有HTTP响应头。所以问题的根本原因我们就找到了,当html2canvas尝试以跨域的方式去读取图片数据时,它读取到的是浏览器的缓存数据,而且因为我们没有给DOM节点中的标签添加crossorigin=”anonymous”属性,所以缓存数据是不带Access-Control-Allow-Origin响应头的,进而导致html2canvas库读取到的图片数据污染了生成的canvas对象,最终致使canvas导出数据报错
安全性和“被污染”的 canvas
由于在
[
- 在
[
](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/canvas)
的上下文上调用[
getImageData()](https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/getImageData)
- 在
[
](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/canvas)
上调用[
toBlob()](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toBlob)
- 在
[
](https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/canvas)
上调用[
toDataURL()](https://developer.mozilla.org/zh-CN/docs/Web/API/HTMLCanvasElement/toDataURL)
这种机制可以避免未经许可拉取远程网站信息而导致的用户隐私泄露。
资料
- Cross-Origin Resource Sharing (CORS)
- html2canvas: Screenshots with JavaScript
- HTMLCanvasElement.toDataURL()
小程序
由于小程序没有DOM
,故不能使用html2canvas
库, 我们采用封装Canvas AP
I来作图,因为使用小程序的downloadFile
api,故没有跨域问题,但需要配置download
域名白名单
基本用法
小程序端中采用了自行封装了一套方法用于绘制文本、图像、矩形、线段等,通过对象配置形式实现画图