天天看点

提高html2canvas截图精度 / 提高dpi

项目中要实现div的截图功能,使用了html2canvas截的图比较模糊,我之前也记录过这个问题,html2canvas 实现网页截图,但是现在要对截图的精度进行优化,截出来的图片要实现打印照片的功能,也就是说html2canvas截图至少要达到300dpi,这样打印出来的图片才不会失真 !这个问题真是难到我了,我在网上搜了很多解决html2canvas截图不清楚的文章看,发现大部分网友都赞同先放大canvas到2倍,然后再缩小画布(渲染的)大小,要设置canvas的画布大小,使用的是canvas.width 和 canvas.height;要设置画布的实际渲染大小,使用的style或CSS设置的 width 和height,只是简单的对画布进行缩放。比如:

var scaleBy=2;//缩放比例
		var owidth=$("#cj1").outerWidth();   //准备截图div的宽
		var oheight=$("#cj1").outerHeight();
		var mycanvas = document.createElement("canvas");
		mycanvas.height = oheight*scaleBy;
		mycanvas.width = owidth*scaleBy;
		mycanvas.style.width = owidth + "px";
		mycanvas.style.height = oheight + "px";
		var cxt = mycanvas.getContext("2d");
		cxt.scale(scaleBy, scaleBy);
                html2canvas(document.getElementById("cj1"), {
		    canvas:mycanvas,
	            onrendered: function(canvas) {
	            document.body.appendChild(canvas);
	        },
	    });
           

( 注:outerWidth() 方法返回第一个匹配元素的外部宽度,返回值包括元素的width+padding+border,不包括margin,如果要包含margin,请使用 outerWidth(true) )。

按照上面的写法,最后截图出现的canvas如下:

<canvas width="320" height="180" style="width:160px;height:90px;"></canvas>
           

这表明生成的canvas的实际大小的320px × 180px,但是实际渲染到页面的大小是160px × 90px,相当于缩小一倍来显示。要使canvas适配高倍屏,就是要将canvas放大到设备像素比来绘制,最后将canvas压缩成一倍的物理大小来展示。

经过测试,放大再缩小之后的截图的确比没有处理过的截图清楚很多(毕竟缩小一倍来显示),但是截出来的图片的dpi仍然是96dpi。我想实现的是前端可以自己控制截图的dpi,前端设置dpi为300,那么截出来的图片就是分辨率为300dpi的。于是我又去网上进行搜索,终于发现了可能解决问题的方法(究竟解没解决再说)。我阅读了博客解决html2canvas截图模糊的问题,发现html2canvas开发的作者,已经考虑到了提高dpi的问题并在github上进行了解答,也对插件进行了一下变动,具体详见Add dpi/scale options for custom resolution,主要思想是:

When a custom 

scale

 is set, the canvas' width/height are multiplied by that scale while keeping its CSS width/height at the original. Then 

ctx.scale

 is used to scale all future canvas actions (see here for more info).

The option 

{dpi: 96}

 is equivalent to 

{scale: 1}

, and larger values of either option will increase the resolution. If both options are present, 

scale

 is ignored in favour of 

dpi

.

百度翻译过来是这样的:

当设置自定义比例尺时,画布的宽度/高度乘以该比例尺,同时保持其CSS宽度/高度为原始值。然后,使用ctx.scale来缩放所有未来的画布动作(参见此处以获得更多信息)。

选项{dpi:96}等价于{scale:1},并且任何选项的更大值都将提高分辨率。如果存在两个选项,scale则忽略使用dpi的比例。

这样一读方法好像与之前网友说的解决办法是一样的。继续往下看,

提高html2canvas截图精度 / 提高dpi

发现这个需求的变动作者没有添加到html2canvas官网文件上,但是作者已经在自己的github上对插件进行了scale和dpi选项的添加。于是我把文件拉了下来,地址---增加了dpi和scale两个选项之后的html2canvas源码(0.5.0-beta4)。html2canvas.js中做了变动的地方应该是这里:

提高html2canvas截图精度 / 提高dpi

这也符合上面的描述,画布的宽高分别乘比例尺scale,然后缩小画布的css渲染的宽高,使得画布显示时缩小到1:1。而且scale=dpi/96,也就是说我设了300dpi,就是将画布按照原来的比例扩大3.125倍。但是只是画布在显示的时候进行缩小,实际的画布的dpi还是96(这是截图图片默认分辨率),也就是canvas.toDataURL()形成的图片大小变成了原图的3.125倍。

使用方式:

html2canvas(element, {
      dpi: 300,
	onrendered: function(canvas){
        ...
    }
});
           

至此,之前的想改变截图的dpi的功能还没有实现,但是图片是清楚一点了,之后有其他的解决办法再记录。

参考文章:

html5 canvas在高倍屏下变模糊的处理办法

解决html2canvas截图模糊的问题

Add dpi/scale options for custom resolution

html2canvas截图如何解决跨域的问题?