Javascript Firefox使用drawImage将SVG图像呈现到HTML5画布时出错
我正在尝试使用画布将外部svg图标转换为base64 png。它在除Firefox之外的所有浏览器中都能工作,Firefox会抛出一个错误“NS\u error\u NOT\u AVAILABLE”Javascript Firefox使用drawImage将SVG图像呈现到HTML5画布时出错,javascript,firefox,svg,html5-canvas,base64,Javascript,Firefox,Svg,Html5 Canvas,Base64,我正在尝试使用画布将外部svg图标转换为base64 png。它在除Firefox之外的所有浏览器中都能工作,Firefox会抛出一个错误“NS\u error\u NOT\u AVAILABLE” 有人能帮我吗?提前感谢。Firefox不支持将SVG图像绘制到画布,除非SVG文件在根元素上具有宽度/高度属性,并且这些宽度/高度属性不是百分比。这是一个很好的例子 您需要编辑icon.svg文件,使其符合上述标准。如前所述,这是一个开放性错误,原因是Firefox在绘制到画布时接受的svg大小规范
有人能帮我吗?提前感谢。Firefox不支持将SVG图像绘制到画布,除非SVG文件在根
元素上具有宽度/高度属性,并且这些宽度/高度属性不是百分比。这是一个很好的例子
您需要编辑icon.svg文件,使其符合上述标准。如前所述,这是一个开放性错误,原因是Firefox在绘制到画布时接受的svg大小规范受到限制。有一个变通办法 Firefox要求SVG本身具有明确的宽度和高度属性。我们可以通过将SVG获取为XML并对其进行修改来添加这些内容
var img=newimage();
var src=“icon.svg”;
//请求svg文件的XML
var request=new XMLHttpRequest();
request.open('GET',src,true)
request.onload=函数(){
//一旦请求返回,解析响应并获取SVG
var parser=新的DOMParser();
var result=parser.parseFromString(request.responseText,'text/xml');
var inlineSVG=result.getElementsByTagName(“svg”)[0];
//添加Firefox需要的属性。这些属性应该是绝对值,而不是相对值
setAttribute('width','48px');
setAttribute('height','48px');
//将SVG转换为数据uri
var svg64=btoa(新的XMLSerializer().serializeToString(inlineSVG));
var image64='数据:image/svg+xml;base64'+svg64;
//将其设置为图像源
img.src=img64;
//做你的画布工作
img.onload=函数(){
var canvas=document.createElement(“canvas”);
canvas.width=this.width;
canvas.height=this.height;
var ctx=canvas.getContext(“2d”);
ctx.drawImage(this,0,0);
var dataURL=canvas.toDataURL(“image/png”);
返回dataURL;
};
}
//发送请求
request.send()代码>这并不是最健壮的解决方案,但这项技术为我们的目的发挥了作用。提取viewBox
数据,并将这些维度用于宽度/高度属性
仅当遇到的第一个视图框
的大小能够准确表示SVG文档的大小时,这才有效,但并非所有情况下都是如此
// @svgDoc is some SVG document.
let svgSize = getSvgViewBox(svgDoc);
// No SVG size?
if (!svgSize.width || !svgSize.height) {
console.log('Image is missing width or height');
// Have size, resolve with new SVG image data.
} else {
// Rewrite SVG doc
let unit = 'px';
$('svg', svgDoc).attr('width', svgSize.width + unit);
$('svg', svgDoc).attr('height', svgSize.height + unit);
// Get data URL for new SVG.
let svgDataUrl = svgDocToDataURL(svgDoc);
}
function getSvgViewBox(svgDoc) {
if (svgDoc) {
// Get viewBox from SVG doc.
let viewBox = $(svgDoc).find('svg').prop('viewBox').baseVal;
// Have viewBox?
if (viewBox) {
return {
width: viewBox.width,
height: viewBox.height
}
}
}
// If here, no viewBox found so return null case.
return {
width: null,
height: null
}
}
function svgDocToDataURL(svgDoc, base64) {
// Set SVG prefix.
const svgPrefix = "data:image/svg+xml;";
// Serialize SVG doc.
var svgData = new XMLSerializer().serializeToString(svgDoc);
// Base64? Return Base64-encoding for data URL.
if (base64) {
var base64Data = btoa(svgData);
return svgPrefix + "base64," + base64Data;
// Nope, not Base64. Return URL-encoding for data URL.
} else {
var urlData = encodeURIComponent(svgData);
return svgPrefix + "charset=utf8," + urlData;
}
}
svg图标是否具有宽度和高度属性?如果是,它们是百分比吗?嗨,Robert,这是一个svg文件,不是svg dom元素,我们可以为它指定任何宽度/高度。我在页面中使用这个svg,因为它没有回答我的问题。icon.svg在根
元素上是否具有宽度/高度属性。如果是,这些属性值是百分比吗?svg图标是使用Adobe Illustrator生成的,我在svg文件中看不到任何宽度/高度。除了调用drawImage()
甚至没有抛出错误之外,我也遇到了同样的问题。在中添加宽度/高度确实解决了它!想发布一个指向那个bug的链接吗?跟踪fix会很有趣的progress@tivoni我已经添加了一个链接,但是在w3c定义应该发生什么之前,这个bug不会有任何进展。这个评论显示了一个可能的解决方法:
// @svgDoc is some SVG document.
let svgSize = getSvgViewBox(svgDoc);
// No SVG size?
if (!svgSize.width || !svgSize.height) {
console.log('Image is missing width or height');
// Have size, resolve with new SVG image data.
} else {
// Rewrite SVG doc
let unit = 'px';
$('svg', svgDoc).attr('width', svgSize.width + unit);
$('svg', svgDoc).attr('height', svgSize.height + unit);
// Get data URL for new SVG.
let svgDataUrl = svgDocToDataURL(svgDoc);
}
function getSvgViewBox(svgDoc) {
if (svgDoc) {
// Get viewBox from SVG doc.
let viewBox = $(svgDoc).find('svg').prop('viewBox').baseVal;
// Have viewBox?
if (viewBox) {
return {
width: viewBox.width,
height: viewBox.height
}
}
}
// If here, no viewBox found so return null case.
return {
width: null,
height: null
}
}
function svgDocToDataURL(svgDoc, base64) {
// Set SVG prefix.
const svgPrefix = "data:image/svg+xml;";
// Serialize SVG doc.
var svgData = new XMLSerializer().serializeToString(svgDoc);
// Base64? Return Base64-encoding for data URL.
if (base64) {
var base64Data = btoa(svgData);
return svgPrefix + "base64," + base64Data;
// Nope, not Base64. Return URL-encoding for data URL.
} else {
var urlData = encodeURIComponent(svgData);
return svgPrefix + "charset=utf8," + urlData;
}
}