实现HTML页面保存为图片
2017-12-07 19:50
169 查看
一、实现HTML页面保存为图片
1.1 已知可行方案
现有已知能够实现网页保存为图片的方案包括:方案1:将DOM改写为canvas,然后利用canvas的toDataURL方法实现将DOM输出为包含图片展示的
data URI
方案2:使用
html2canvas.js实现(可选搭配
Canvas2Image.js实现网页保存为图片)
方案3:使用
rasterizeHTML.js实现
1.2 解决方案的选择
方案1:需要手动计算每个DOM元素的Computed Style,然后需要计算好元素在canvas的大小位置等属性。
方案1难点:
相当于完全重写了整个页面的布局样式,增加了工作量。
由于canvas中没有的对象概念,对于元素丰富、布局复杂的页面,不易重构。
所有DOM元素改写进canvas会带来一些困难,例如:难以支持响应式,图片元素清晰度不佳和文字点击区域识别问题等。
方案2:该类功能中Github上stars最多(至今仍在维护),Stack Overflow亦有丰富的讨论。只需简单调用html2canvas方法并设定配置项即可。
方案3:该方案的限制较多,目前仅支持3类可转为canvas的目标格式: 页面url,html字符串和document对象。
小结: html2canvas是目前实现网页保存为图片功能的综合最佳选择。
1.3 html2canvas的使用方法
官方GitHub:https://github.com/niklasvh/h...以下描述针对html2canvas版本是
0.5.0-beta4
1.3.1 实现保存为图片的第一步:html转为canvas
基于html2canvas.js可将一个元素渲染为canvas,只需要简单的调用
html2canvas(element[, options]);即可。下列
html2canvas方法会返回一个包含有
<canvas>元素的
promise:
html2canvas(document.body).then(function(canvas) { document.body.appendChild(canvas); });
1.3.2 实现保存为图片的第二步:canvas转image
上一步生成的canvas即为包含目标元素的<canvas>元素对象。实现保存图片的目标只需要将canvas转image即可。
这里的转换方案有
2种:
方案1:基于原生canvas的
toDataURL方法将canvas输出为
data: URI类型的图片地址,再将该图片地址赋值给
<image>元素的src属性即可
方案2:使用第三方库
Canvas2Image.js,调用其
convertToImage方法即可(GitHub)
实际上,
Canvas2Image.js也是基于
canvas.toDataURL的封装,相比原生的canvas API对于转为图片的功能上考虑更为具体(未压缩的包大小为7.4KB),适合项目使用。
二、生成图片的清晰度优化方案
2.1 基础的清晰度优化方案
最终图片的清晰度取决于第一步中html转换成的canvas的清晰度。
现有解决方案参考;
html5 canvas在高倍屏下变模糊的处理办法
html5 canvas绘制图片模糊的问题
其基本原理为:
将
canvas的属性
width和
height属性放大为2倍(或者设置为
devicePixelRatio倍),最后将canvas的CSS样式width和height设置为原先1倍的大小。
例如:希望在html中实际显示的
<canvas>宽高分别为
160px,
90px则可作如下设置
<canvas width="320" height="180" style="width:160px;height:90px;"></canvas>
参考上述文档具体的使用案例如下;
convert2canvas() { var shareContent = YourTargetElem; var width = shareContent.offsetWidth; var height = shareContent.offsetHeight; var canvas = document.createElement("canvas"); var scale = 2; canvas.width = width * scale; canvas.height = height * scale; canvas.getContext("2d").scale(scale, scale); var opts = { scale: scale, canvas: canvas, logging: true, width: width, height: height }; html2canvas(shareContent, opts).then(function (canvas) { var context = canvas.getContext('2d'); var img = Canvas2Image.convertToImage(canvas, canvas.width, canvas.height); document.body.appendChild(img); $(img).css({ "width": canvas.width / 2 + "px", "height": canvas.height / 2 + "px", }) }); }
2.2 进阶的清晰度优化方案
上述设置可以解决通常情况下图片不清晰的问题,不过探索并没有结束。实际在我们的项目中,即使作出
2.1节的设置后,大果粒一般的渲染结果依然尴尬。
下面直接给出3条进一步的优化策略:
更改
百分比布局为
px布局(如果原先是百分比布局的话)
关闭canvas默认的
抗锯齿设置
设置模糊元素的
width和
height为素材原有宽高,然后通过
transform: scale进行缩放。这里
scale的数值由具体需求决定。
基本原理
如果原来使用百分比设置元素宽高,请更改为
px为单位的宽高,避免样式二次计算导致的模糊
默认情况下,canvas的抗锯齿是开启的,需要
关闭抗锯齿来实现图像的锐化(MDN: imageSmoothingEnabled )
除了canvas可以通过扩大2倍宽高然后缩放至原有宽高来提高清晰度,对于DOM中其他的元素也可以使用
css样式的
scale来实现同样的缩放
例: html2canvas配置
convert2canvas() { var cntElem = $('#j-sec-end')[0]; var shareContent = cntElem;//需要截图的包裹的(原生的)DOM 对象 var width = shareContent.offsetWidth; //获取dom 宽度 var height = shareContent.offsetHeight; //获取dom 高度 var canvas = document.createElement("canvas"); //创建一个canvas节点 var scale = 2; //定义任意放大倍数 支持小数 canvas.width = width * scale; //定义canvas 宽度 * 缩放 canvas.height = height * scale; //定义canvas高度 *缩放 canvas.getContext("2d").scale(scale, scale); //获取context,设置scale var opts = { scale: scale, // 添加的scale 参数 canvas: canvas, //自定义 canvas // logging: true, //日志开关,便于查看html2canvas的内部执行流程 width: width, //dom 原始宽度 height: height, useCORS: true // 【重要】开启跨域配置 }; html2canvas(shareContent, opts).then(function (canvas) { var context = canvas.getContext('2d'); // 【重要】关闭抗锯齿 context.mozImageSmoothingEnabled = false; context.webkitImageSmoothingEnabled = false; context.msImageSmoothingEnabled = false; context.imageSmoothingEnabled = false; // 【重要】默认转化的格式为png,也可设置为其他格式 var img = Canvas2Image.convertToJPEG(canvas, canvas.width, canvas.height); document.body.appendChild(img); $(img).css({ "width": canvas.width / 2 + "px", "height": canvas.height / 2 + "px", }).addClass('f-full'); }); }
例: DOM元素样式:
.targetElem {width: 54px;height: 142px;margin-top:2px;margin-left:17px;transform: scale(0.5)}
三、含有跨域图片的配置
由于canvas对于图片资源的同源限制,如果画布中包含跨域的图片资源则会污染画布,造成生成图片样式混乱或者html2canvas方法不执行等问题。
以下主要解决两类跨域的图片资源:包括已配置过CORS的
CDN中的图片资源和
微信用户头像图片资源。
3.1 针对CDN中的图片的配置
要求CDN的图片配置好CORS。
CDN配置好后,通过chrome开发者工具可以看到响应头中应含有
Access-Control-Allow-Origin的字段。
开启
html2canvas的
useCORS配置项。即作如下设置:
var opts = {useCORS: true}; html2canvas(element, opts);
注意:
如果没有开启
html2canvas的
useCORS配置项,
html2canvas会正常执行且不会报错,但是不会输出对应的CDN图片
(已测试同时包含
CDN的图片和
本地图片的资源的页面,但是只有
本地图片能够被正常渲染出来)
3.2 针对微信用户头像的配置
如果需要将微信平台中的用户头像一并保存为图片,
3.1的方案无能为力。可通过配置服务端
代理转发(forward)实现,此处不赘述。
其他注意事项
1. margin的遮挡问题
微信中,唤出长按保存图片的菜单要求长按的对象直接是
<image>元素,如果
<image>元素上方存在遮挡,则不会唤出菜单。
而事实上,引发遮挡的并不只是非
<image>元素,还可能是
margin属性。例如:若在页面底部,对一个绝对定位的元素设置了数值很大的
margin-top,则
margin-top所涉及的区域,均无法长按唤出菜单。解决方案:将
margin-top改用为
top即可。
2. 安卓版微信保存图片失败的问题
canvas2img默认保存图片的格式为
png,而在安卓版微信中所生成的图片尽管能长按唤出保存图片的菜单,但是无法正确保存到本地相册。
解决方案:设置
canvas2img的生成图片格式配置项为
jpeg即可。
3. JPEG的黑屏问题
设置canvas2img输出格式为
jpeg,会有一定几率导致生成的图片包含大量的黑色块。
可能的解决方案:缩减部分图片元素的体积和尺寸大小。
4. 不能保留动效
在图片的转化前,必须
停止或者删除动效后才能正确渲染出图片,否则生成的图片是破裂的。
相关文章推荐
- 将html页面保存成图片,图片写入pdf的实现方法(推荐)
- php动态网页实现页面静态化 通过在初次被访问时生成html文件保存起来,下次该PHP程序被访问时就直接找到以前被访问过的html页面
- 纯html实现将网页页面分享到微信朋友圈添加缩略图图片的方法
- data URI scheme(图片直接保存在html页面的方法)
- php实现将HTML页面转换成word并且保存的方法
- html页面保存成图片,图片写入pdf
- php动态网页实现页面静态化 通过在初次被访问时生成html文件保存起来,下次该PHP程序被访问时就直接找到以前被访问过的html页面
- Swift4.0版-H5页面实现长按保存图片
- 移动设备的HTML页面中图片实现滚动加载
- php动态网页实现页面静态化 通过在初次被访问时生成html文件保存起来,下次该PHP程序被访问时就直接找到以前被访问过的html页面
- 移动设备的HTML页面中图片实现滚动加载
- htmlcanvas2实现将网页生成图片,自定义保存图片的名称
- CHtmlView浏览器双击页面保存图片的初步实现
- Java 实现HTML 页面转成image 图片
- 一个小型的网站,比如个人网站,可以使用最简单的html静态页面就实现了,配合一些图片达到美化效果,所有的页面均存放在一个目录下,这样的网站对系统架构、性能的要求都很简单,随着互联网业务的不断丰富,网站
- html页面保存成图片,图片写入pdf
- Java 实现HTML 页面转成image 图片
- Web页面截图或HTML内容保存为图片
- php动态网页实现页面静态化 通过在初次被访问时生成html文件保存起来,下次该PHP程序被访问时就直接找到以前被访问过的html页面
- 用Seam实现:图片上传 + 保存到数据库 + 从数据库读出图片并显示到页面中