Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/428.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用foreignObject从svg获取画布数据URI时出现问题_Javascript_Image_Canvas_Svg - Fatal编程技术网

Javascript 使用foreignObject从svg获取画布数据URI时出现问题

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>

嗨,我有以下问题

我正在生成一个SVG图像()

图像生成正确且看起来正常。 现在,我需要获取数据URI,但每次我尝试从canvas.toDataURL()获取该URI时,此消息会显示未捕获的DomeException:未能在“HtmlCanvaElement”上执行“toDataURL”:可能无法导出受污染的canvas。(……

我创建了一些示例代码来说明这种情况

</!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 如果您希望将DOM元素光栅化,那么您应该解析DOM及其所有应用的样式,并使用画布绘制方法重新生成它。
这样做,你可以绕过大多数安全问题,没有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:)