HTML如何转化为canvas教程
预览图
老规矩, 先放图
第一个红格子是DOM渲染的, 第二个带边框的红格子是用html的代码在canvas画出来的, 没有使用canvas的api哦. 本文最后贴出了代码.
原理
本文转化的实现, 以及本文下半部分所介绍的html2canvas.js框架的原理均出自于, mdn的这个篇文章将 DOM 对象绘制到 canvas 中
首先我们不能直接把 HTML 画到 canvas 上。我们需要使用一个SVG 图像包含想要呈现的内容 。为了绘制 HTML 内容,你要先用<foreignObject>
元素包含 HTML 内容,然后再将这个 SVG 图像绘制到你的 canvas 中。
这里的foreignObject
元素允许包含外来的XML命名空间,其图形内容是别的用户代理绘制的。这个被包含的外来图形内容服从SVG变形和合成。
我们转化的步骤为:
1. 创建一个blob 对象, 其 MIME 应为 “image/svg+xml”。
2. 一个 <svg>
元素。
3. 在 SVG 元素中包含的 <foreignObject>
元素。
4. 包裹到 <foreignObject>
中的(格式化好的) HTML。
第一步预览图的代码
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div class="wrapper">
<div class="target" style="
width: 100px;
height: 100px;
background: red;
margin-bottom: 50px;
">123</div>
</div>
<canvas id="canvas" style="border:2px solid black;" width="200" height="200">
</canvas>
<script>
let canvas = document.getElementById('canvas');
let ctx = canvas.getContext('2d');
let target = document.getElementsByClassName('wrapper');
// 创造svg
let data = `
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml" style="font-size:40px">
${target[0].innerHTML}
</div>
</foreignObject>
</svg>
`
let DOMURL = window.URL || window.webkitURL || window;
let img = new Image();
let svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
let url = DOMURL.createObjectURL(svg);
// 根据svg生产url
img.onload = function () {
ctx.drawImage(img, 0, 0);
DOMURL.revokeObjectURL(url); // 摧毁刚刚生产的url
}// 注册回调函数
img.src = url;
// 将图片url塞到img里
</script>
</body>
</html>
有几个需要注意的点:
1. 此方法中插入的html必须是有效的html
2. 必须使用内联样式, 并且支持部分样式,
3. 已访问的链接样式(:visited
)不会对 SVG 图像中的链接生效,因此无法获取浏览历史;SVG 图像中也不会渲染原生主题,因此借此检测用户的平台也会更困难。
4. 此外,您也不能在 SVG 图像中各种引入脚本文件,因此不会有从其他脚本文件访问 DOM 的风险。SVG 图像中的 DOM 元素也不能接收事件的输入,因此无法将敏感信息载入到一个表单控件(如将完整路径载入到 file <input>
元素中)渲染再通过读取图像获取这些信息。
5. 这个解决方案所依赖的 SVG 图像在实现上是非常严格
的。如果引入了外部的图片会污染canvas画布. 但是接下来说介绍的html2canvas
可以解决这个问题!!!
html2canvas
框架官网地址: http://html2canvas.hertzen.com/
本文使用介绍基于1.0.0-alpha.12版本
效果图
这次直接有框架生成的canvas, 因此没有了边框. 下面是代码
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
.target {
width: 100px;
height: 100px;
background: red;
margin-bottom: 50px;
}
</style>
</head>
<body>
<div class="wrapper">
<div class="target">123</div>
</div>
<script src="./canvas.js"></script>
<script>
window.onload = function() {
html2canvas(document.querySelector(".wrapper")).then(canvas => {
document.body.appendChild(canvas)
});
}
</script>
</body>
</html>
.then
是promise语法, 不了解es6的同学可以看看阮一峰es6入门, 写的非常好.
上面的代码可以看到, 支持内联样式了, 同时使用起来也很简单. 那么上文所留下的悬念: 如何加载外部图片呢? 接下来将会和html2canvas的配置项一起介绍给大家.
html2canvas配置项
名称 | 默认 | 描述 |
---|---|---|
async | true | 是否异步解析和渲染元素 |
allowTaint | false | 是否允许跨原始图像污染画布 |
backgroundColor | ffffff | 画布背景颜色 |
canvas | null | 你自己提供一个canvas用作绘图, 此项不填框架会自动生成一个canvas标签 |
foreignObjectRendering | false | 就是是否用上面所提到的foreignObject这个来渲染, 默认为遍历dom树 |
imageTimeout | 15000 | 设置图像加载的超时时间(以毫秒为单位)设置0为禁用超时 |
ignoreElements | (element) => false | Predicate function which removes the matching elements from the render. 大致的意思是匹配元素, 在你渲染的时候去掉那个匹配的元素 |
logging | true | 启用日志记录以进行调试 |
onclone | null | Callback function which is called when the Document has been cloned for rendering, can be used to modify the contents that will be rendered without affecting the original source document.这个我也不知道是干嘛的, 欢迎大家踊跃提出建议 |
proxy | null | 填写url, 设置代理,用于加载跨源图像. 如果为null,跨域图片则不会加载 |
removeContainer | true | Whether to cleanup the cloned DOM elements html2canvas creates temporarily(还得研究, 不知道那个cloned DOM是干嘛的) |
scale | window.devicePixelRatio | 设置渲染的比例。默认为浏览器设备像素比率 |
useCORS | false | 是否尝试使用CORS从服务器加载图像 |
width | canvas宽度 | |
height | canvas高度 | |
X | Element x偏移量 | |
y | Element y偏移量 |
开启图片跨域
效果图
图片随便在网上找的
代码
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
img {
width: 500px;
}
</style>
</head>
<body>
<div class="wrapper">
<img src="https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1533212152031&di=f26250570f7d5f2e7895c7c13e96d61a&imgtype=0&src=http%3A%2F%2Fh.hiphotos.baidu.com%2Fimage%2Fpic%2Fitem%2F267f9e2f07082838304837cfb499a9014d08f1a0.jpg"></img>
</div>
<script src="./canvas.js"></script>
<script>
window.onload = function() {
html2canvas(document.querySelector(".wrapper"), {
allowTaint: true,
useCORS: true,
}).then(canvas => {
document.body.appendChild(canvas)
});
}
</script>
</body>
</html>
ps: 如果在小瓶图片变糊, 可以试着设置那个scale参数, 或者采用在canvas的width属性设置例如1000, 在css中设置width: 500px; 来进行压缩
如果你需要保存为本地图片可以采用Canvas2Image.js这个框架, 具体内容百度, 本文不做介绍
上一篇: 漫画:我那麼喜歡你,你喜歡我一下会死啊?
下一篇: python-网络图片下载(两种方式)
推荐阅读
-
html5指南-3.如何实现html元素拖拽功能_html5教程技巧
-
html2canvas把div保存图片高清图(图文教程)
-
HTML5 Canvas实现图片缩放、翻转、颜色渐变的代码示例_html5教程技巧
-
HTML5 Canvas绘制文本及图片的基础教程
-
html5 canvas 画图教程案例分析
-
html5 Canvas画图教程(3)—canvas出现1像素线条模糊不清的原因
-
html5 Canvas画图教程(2)—画直线与设置线条的样式如颜色/端点/交汇点
-
html5 Canvas画图教程(1)—画图的基本常识
-
html5 Canvas画图教程(9)—canvas中画出矩形和圆形
-
html5 Canvas画图教程(4)—未闭合的路径及渐变色的填充方法