我需要拍摄div的ScreenShot,并将其发送到服务器(Java)进行存储。我公司项目中的现有代码使用Html2Canvas.js,它获取元素(div,body…)并返回base64数据URI,工作正常,但在Chrome中冻结了应用程序。因此,我正在寻找其他解决方案,并从堆栈溢出中找到了以下代码。
var 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="height:200px;width:200px;background-color:red;font-size:40px">' +
'<em></em> l ' +
'<span style="color:white; text-shadow:0 0 2px blue;">' +
'</span>' +
'</div>' +
'</foreignObject>' +
'</svg>';
var DOMURL = window.URL || window.webkitURL || window;
var svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
var url = DOMURL.createObjectURL(svg);
document.getElementById("image1").src=url;
<img id='image1' width="200px" height="200px"/>
这里我得到的url是Blob url(Blob:https%3A//fidd.jshell.net/a5b366a2-ff0c-4c7b-9b20-a80395d7f536),我可以将其用作img src,或者如果我直接在新选项卡中打开该url,它也会打开。有没有办法从blob URL或blob对象中获得这样的base64 dataUri(数据:image/png;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAA)?
@thepio关于如何从Blob中获取数据URI是正确的:使用FileReader
及其readAsDataURL()
方法
这将为您提供Blob/File的base64编码数据URI表示。
但是,让我们从您正在做的事情后退一步:
您正在使用破解来获得HTML标记的某种屏幕截图,使用SVG的foreignObject。
您绝对不需要Blob,也不需要base64版本来在<img>
元素中显示这一点:
您只需要将dataURI的标头设置为'data:image/svg+xml; charset=utf8, '
,然后附加svg标记,这将节省多达30%的数据大小
不过有些字符需要编码,所以您可以直接调用encodeURIComponent(yourSVGMarkup)
。
var svgString = '<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="height:200px;width:200px;background-color:red;font-size:40px">' +
'<em></em> l ' +
'<span style="color:white; text-shadow:0 0 2px blue;">' +
'I'm white'+
'</span>' +
'</div>' +
'</foreignObject>' +
'</svg>';
var dataURI = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgString);
img.src = dataURI;
<img id="img" />
但这只会保存svg版本,在IE<11,因为这些浏览器不支持foreignObject
元素。
我想你想要的是光栅版。
为此,您可以尝试使用drawImage
方法在画布上绘制svg,然后调用画布的导出方法之一(toDataURL()
或toBlob()
)。
但这将污染Safari9中的画布,因为它们在foreignObject
和IE<Edge与svg总体上存在安全问题。污染画布将使其导出方法不可用,整个操作将失败。
此外,即使在支持它的浏览器中,也有另一个很大的限制:
- dataURI版本中的元素不在文档中,无法请求任何其他外部资源(CSS、字体、图像…),这意味着在将其转换为dataURI之前,您需要将其(或最后两个版本的dataURI编码版本)附加到svg标记中
也许不那么重要,但某些浏览器的默认样式将在某些元素(主要是输入)上消失。
所以在你的情况下,我会克制自己使用这个黑客
获得HTML元素的光栅版本的唯一可接受的方法是使用画布绘制方法来绘制它,就像html2canvas和其他库所做的那样。
所以我会尝试解决当前看起来不正常的问题。
如果您不需要光栅版本,最简单的方法是将HTML标记保存在数据库中,然后将其附加到文档中(但请确保已将其清除)。
您可以使用FileReader并这样做:
var 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="height:200px;width:200px;background-color:red;font-size:40px">' +
'<em></em> l ' +
'<span style="color:white; text-shadow:0 0 2px blue;">' +
'</span>' +
'</div>' +
'</foreignObject>' +
'</svg>';
var DOMURL = window.URL || window.webkitURL || window;
var svg = new Blob([data], {type: 'image/svg+xml;charset=utf-8'});
var url = DOMURL.createObjectURL(svg);
var base64data;
var reader = new window.FileReader();
reader.readAsDataURL(svg);
reader.onloadend = function() {
base64data = reader.result;
document.getElementById("image1").src=base64data;
}
<img id='image1' width="200px" height="200px"/>
关于readAsDataURL
:的文档说明如下
开始读取指定Blob的内容,一旦完成,result属性将包含一个数据:表示文件数据的URL。