Javascript 使用foreignObject从svg获取画布数据URI时出现问题
嗨,我有以下问题 我正在生成一个SVG图像() 图像生成正确且看起来正常。 现在,我需要获取数据URI,但每次我尝试从canvas.toDataURL()获取该URI时,此消息会显示未捕获的DomeException:未能在“HtmlCanvaElement”上执行“toDataURL”:可能无法导出受污染的canvas。(…… 我创建了一些示例代码来说明这种情况Javascript 使用foreignObject从svg获取画布数据URI时出现问题,javascript,image,canvas,svg,Javascript,Image,Canvas,Svg,嗨,我有以下问题 我正在生成一个SVG图像() 图像生成正确且看起来正常。 现在,我需要获取数据URI,但每次我尝试从canvas.toDataURL()获取该URI时,此消息会显示未捕获的DomeException:未能在“HtmlCanvaElement”上执行“toDataURL”:可能无法导出受污染的canvas。(…… 我创建了一些示例代码来说明这种情况 </!DOCTYPE html> <html> <head> <title>
</!DOCTYPE html>
<html>
<head>
<title>SVG to PNG</title>
</head>
<body>
<canvas id="canvas" style="border:2px solid black;" width="200" height="200">
</canvas>
<script type="text/javascript">
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
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="font-size:40px">' +
'<em>I</em> like ' +
'<span style="color:white; text-shadow:0 0 2px blue;">' +
'beer</span>' +
'</div>' +
'</foreignObject>' +
'</svg>';
var domURL = window.URL || window.webkitURL || window;
var img = new Image();
var svg = new Blob([data], {type: 'image/svg+xml'});
var url = domURL.createObjectURL(svg);
img.onload = function () {
ctx.drawImage(img, 0, 0);
domURL.revokeObjectURL(url);
var dataURL = canvas.toDataURL();
console.log(dataURL);
};
img.src = url;
</script>
</body>
</html>
SVG到PNG
var canvas=document.getElementById('canvas');
var ctx=canvas.getContext('2d');
var数据=“”+
'' +
'' +
“我喜欢”+
'' +
“啤酒”+
'' +
'' +
'';
var domURL=window.URL | | window.webkitURL | | window;
var img=新图像();
var svg=newblob([data],{type:'image/svg+xml'});
var url=domURL.createObjectURL(svg);
img.onload=函数(){
ctx.drawImage(img,0,0);
revokeObjectURL(url);
var dataURL=canvas.toDataURL();
log(dataURL);
};
img.src=url;
此代码生成以下图像
这是正确的,但是当执行这些行时
var-dataURL=canvas.toDataURL();
log(dataURL)强>
它抛出了错误。我在imageonload方法中执行此操作,以允许图像完成绘制到画布。如果我试图从onload方法之外获取dataURL,画布还没有完成加载,因此它会给我一个空图像。
我一直在寻找,但我还没有找到答案。这与CORS有关。我已经安装了chrome插件CORS并添加了img,问题是这只是一个例子,基于CORS的解决方案不会有用,因为我正在开发一个运行在一个残废的chrome浏览器上的应用程序(我的意思是,浏览器只显示web应用程序,除了与应用程序交互之外,你不能在那里做任何事情)
注意,您可以使用
检查-->网络-->选择图像并在“源代码”面板中打开,然后将图像复制为数据uri。
我用这种方式得到base64图像,如果我使用像这样的解码器(),它会正确地显示图像。
所以肯定的问题是,我在绘制画布之前获取数据URI
有什么想法吗
提前谢谢
问候
Mauro这与CORS无关。您没有向外部资源发出任何请求 问题在于,绘制svg(而且当它包含html元素时)对于浏览器来说是一个非常敏感的操作 这就是为什么这项技术有很多限制(你不能加载外部资源,脚本被忽略,你不能从外部CSS设置内容样式,所有默认浏览器和操作系统样式都被禁用以避免指纹识别等)。
我不为safari或chrome工作,所以我不能确定,但我认为他们无法在其中一点上提供足够的安全性(safari在v9中实现了这一点,这是一个很好的解决方案) 因此,他们所做的是污染画布,锁定其任何导出方法。(注意,IE
这样做,你可以绕过大多数安全问题,没有UA会污染画布。一些图书馆正是这样做的,最著名的是 如果您想要绘制此图像,则可以在不使用foreignObject的情况下重写它(svg文本比canvas文本有更多选项),然后使用类似于库的方法在画布上渲染它(因为否则IE将污染画布,如前所述)
注意:chrome的问题可以解决,但我不确定这是一个好主意,它在Safari和IE
var canvas=document.getElementById('c');
var ctx=canvas.getContext('2d');
var数据=“”+
'' +
'' +
“我喜欢”+
'' +
“啤酒”+
'' +
'' +
'';
var img=新图像();
//如果我们使用dataURL,chrome看起来会很高兴。。。
var url='data:image/svg+xml;charset=utf8',+encodeURIComponent(数据);
img.onload=函数(){
c、 宽度=此宽度;
c、 高度=此高度;
ctx.drawImage(img,0,0);
var dataURL=canvas.toDataURL();
log(dataURL);
};
img.src=url;
什么是“受污染”画布?尽管您可以在画布中使用未经CORS批准的图像,但这样做会污染画布。画布一旦受污染,您就不能再从画布中提取数据。例如,您不能再使用画布toBlob()、toDataURL()或getImageData()方法;这样做会引发一个安全错误。@TimVermaelen,这里没有涉及跨源代码…只是想知道什么是受污染的画布。因此,斜体描述接近于您无法完成尝试的原因。您的解决方法适用于chrome、firefox和safari:)