如何在 Google 图表中获取带有 svg 内部图像的 png(base64)?
How can I get png(base64) with images inside of svg in Google Charts?
如何在 svg 中获取带有图像的 base64?检查这个 Fiddle 我从另一个问题得到的。如果您看到第二个图形,它不会生成覆盖条形图的图像。
var chart = new google.visualization.ColumnChart(document.getElementById('chart_survey'));
$("[fill='#FFFFFF']").each(function( index, element ) {
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttributeNS(null,'x',element.x.baseVal.value);
svgimg.setAttributeNS(null,'y',element.y.baseVal.value);
svgimg.setAttributeNS(null,'width',element.width.baseVal.value);
svgimg.setAttributeNS(null,'height',element.height.baseVal.value);
svgimg.setAttributeNS(null,'preserveAspectRatio','none');
svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', '${application.contextPath}/images/textura/patt.gif');
$(element).parent().append(svgimg);
});
$('#test').val(chart.getImageURI())
此示例创建一个由图像填充的 svg 容器。在我的示例中,图像是 svg 图像,但您应该能够放入任何类型的图像(jpg、png、gif)。先创建容器,再在容器内创建镜像。
// create svg
var svg = document.createElementNS('http://www.w3.org/2000/svg','svg');
svg.setAttribute('class','shadowed handle_icon_sensors');
svg.setAttribute('height','25');
svg.setAttribute('width','25');
svg.setAttribute('id',idAttr);
svg.setAttribute('z-index','21000');
document.getElementById("zones_container").appendChild(svg);
// create svg image
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttribute('height','25');
svgimg.setAttribute('width','25');
svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href','svg/icon_sensorYellow.svg');
svgimg.setAttribute('x','0');
svgimg.setAttribute('y','0');
document.getElementById(idAttr).appendChild(svgimg);
注意,当转换为src
的img
元素时保留blue
background-color
.
在 .each()
之后尝试
// set namespace attributes
var svg = $("svg").attr({
"xmlns": "http://www.w3.org/2000/svg",
"xmlns:xlink": "http://www.w3.org/1999/xlink"
})[0];
// create `data URI` of `svg`
var dataURI = "data:image/svg+xml;charset=utf-8;base64," + btoa(svg.outerHTML.trim());
// post `svg` as `data URI` to server
$.post("/path/to/server/", {
html: dataURI
}, "html")
.then(function (data) {
// do stuff
// `svg` `data URI`
console.log(data);
}, function (jqxhr, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
});
jsfiddle http://jsfiddle.net/R8A8P/58/
为了将此 svg 保存为 png,从而保持链接 <image>
然后您必须将每个 <image>
的 href
编码为数据 URL 首先。
编辑
我重写了原始片段(仍然可以在编辑历史中找到)。
我将 <image>
标签更改为 <use>
。这导致内存使用量小得多。
我还添加了 IE11 的回退,它接受将外部图像编码为数据 URL,但仍然无法通过 canvas 将 svg 转换为 png。
回退将用 canvas 替换目标 <img>
标签。后者可以由用户通过右键单击来保存。
一些注意事项:
它在 Safari 7 中不起作用,也许在其他过时的 webkit 浏览器中也不起作用。这是一个奇怪的错误,因为它在 localhost 中确实像魅力一样工作,但在任何其他网络上都不会(即使在我的家庭网络上,使用 192.168.xxx)。
IE 9 & IE 10 无法将外部图像转换为数据 URL,CORS 问题。
// What to do with the result (either data URL or directly the canvas if tainted)
var callback = function(d, isTainted) {
if (!isTainted) {
$('#chartImg')[0].src = d;
} else
$('#chartImg')[0].parentNode.replaceChild(d, $('#chartImg')[0]);
};
// The url of the external image (must be cross-origin compliant)
var extURL = 'https://dl.dropboxusercontent.com/s/13dv8vzmrlcmla2/tex2.jpg';
google.load('visualization', '1', {
packages: ['corechart']
})
var encodeCall = getbase64URI.bind(this, extURL, callback);
google.setOnLoadCallback(encodeCall);
// Google Chart part
function drawVisualizationDaily(imgUrl, callback, isTainted) {
var data = google.visualization.arrayToDataTable([
['Daily', 'Sales'],
['Mon', 4],
['Tue', 6],
['Wed', 6],
['Thu', 5],
['Fri', 3],
['Sat', 7],
['Sun', 7]
]);
var chart = new google.visualization.ColumnChart(document.getElementById('visualization'));
chart.draw(data, {
title: "Daily Sales",
width: 500,
height: 400,
hAxis: {
title: "Daily"
}
});
// Link to chart's svg element
var svgNode = chart.ea.querySelector('svg');
// Create a symbol for our image
var symbol = document.createElementNS('http://www.w3.org/2000/svg', 'symbol');
// An svg wrapper to allow size changing with <use>
symbol.setAttributeNS(null, 'viewBox', '0,0,10,10');
symbol.setAttributeNS(null, 'preserveAspectRatio', 'none');
symbol.id = 'background';
// And the actual image, with our encoded image
var img = document.createElementNS('http://www.w3.org/2000/svg', 'image');
img.setAttributeNS(null, 'preserveAspectRatio', 'none');
img.setAttributeNS(null, 'width', '100%');
img.setAttributeNS(null, 'height', '100%');
img.setAttributeNS('http://www.w3.org/1999/xlink', 'href', imgUrl);
symbol.appendChild(img);
svgNode.appendChild(symbol);
var blueRects = $("[fill='#3366cc']");
var max = blueRects.length - 1;
blueRects.each(function(index, element) {
var svgimg = document.createElementNS('http://www.w3.org/2000/svg', 'use');
svgimg.setAttributeNS(null, 'x', element.x.baseVal.value);
svgimg.setAttributeNS(null, 'y', element.y.baseVal.value);
svgimg.setAttributeNS(null, 'width', element.width.baseVal.value);
svgimg.setAttributeNS(null, 'height', element.height.baseVal.value);
svgimg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#background');
svgNode.appendChild(svgimg);
if (index === max && !isTainted) // no need to call it if we don't have our dataURL encoded images
// a load event would be better but it doesn't fire in IE ...
setTimeout(exportSVG.bind(this, svgNode, callback, isTainted), 200);
});
}
function exportSVG(svgNode, callback, isTainted) {
var svgData = (new XMLSerializer()).serializeToString(svgNode);
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = svgNode.getAttribute('width');
canvas.height = svgNode.getAttribute('height');
canvas.getContext('2d').drawImage(this, 0, 0);
var data, isTainted;
try {
data = canvas.toDataURL();
} catch (e) {
data = canvas;
isTainted = true;
}
callback(data, isTainted);
}
img.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData);
}
// A simple function to convert an images's url to base64 data URL
function getbase64URI(url, callback) {
var img = new Image();
img.crossOrigin = "Anonymous";
img.onload = function() {
var c = document.createElement('canvas');
c.width = this.width;
c.height = this.height;
c.getContext('2d').drawImage(this, 0, 0);
var isTainted;
try {
c.toDataURL();
} catch (e) {
isTainted = true;
}
// if the canvas is tainted, return the url
var output = (isTainted) ? url : c.toDataURL();
drawVisualizationDaily(output, callback, isTainted);
}
img.src = url;
}
svg { border: 1px solid yellow; }
img { border: 1px solid green; }
canvas { border: 1px solid red; }
<script src="http://www.google.com/jsapi?.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="visualization"></div>
Right-click this image to save it:
<br>
<img id="chartImg" />
这个html在反应中工作
<a
href={chart.getImageURI()}
download="chart.png">
getImage
</a>
如何在 svg 中获取带有图像的 base64?检查这个 Fiddle 我从另一个问题得到的。如果您看到第二个图形,它不会生成覆盖条形图的图像。
var chart = new google.visualization.ColumnChart(document.getElementById('chart_survey'));
$("[fill='#FFFFFF']").each(function( index, element ) {
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttributeNS(null,'x',element.x.baseVal.value);
svgimg.setAttributeNS(null,'y',element.y.baseVal.value);
svgimg.setAttributeNS(null,'width',element.width.baseVal.value);
svgimg.setAttributeNS(null,'height',element.height.baseVal.value);
svgimg.setAttributeNS(null,'preserveAspectRatio','none');
svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href', '${application.contextPath}/images/textura/patt.gif');
$(element).parent().append(svgimg);
});
$('#test').val(chart.getImageURI())
此示例创建一个由图像填充的 svg 容器。在我的示例中,图像是 svg 图像,但您应该能够放入任何类型的图像(jpg、png、gif)。先创建容器,再在容器内创建镜像。
// create svg
var svg = document.createElementNS('http://www.w3.org/2000/svg','svg');
svg.setAttribute('class','shadowed handle_icon_sensors');
svg.setAttribute('height','25');
svg.setAttribute('width','25');
svg.setAttribute('id',idAttr);
svg.setAttribute('z-index','21000');
document.getElementById("zones_container").appendChild(svg);
// create svg image
var svgimg = document.createElementNS('http://www.w3.org/2000/svg','image');
svgimg.setAttribute('height','25');
svgimg.setAttribute('width','25');
svgimg.setAttributeNS('http://www.w3.org/1999/xlink','href','svg/icon_sensorYellow.svg');
svgimg.setAttribute('x','0');
svgimg.setAttribute('y','0');
document.getElementById(idAttr).appendChild(svgimg);
注意,当转换为src
的img
元素时保留blue
background-color
.
在 .each()
// set namespace attributes
var svg = $("svg").attr({
"xmlns": "http://www.w3.org/2000/svg",
"xmlns:xlink": "http://www.w3.org/1999/xlink"
})[0];
// create `data URI` of `svg`
var dataURI = "data:image/svg+xml;charset=utf-8;base64," + btoa(svg.outerHTML.trim());
// post `svg` as `data URI` to server
$.post("/path/to/server/", {
html: dataURI
}, "html")
.then(function (data) {
// do stuff
// `svg` `data URI`
console.log(data);
}, function (jqxhr, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
});
jsfiddle http://jsfiddle.net/R8A8P/58/
为了将此 svg 保存为 png,从而保持链接 <image>
然后您必须将每个 <image>
的 href
编码为数据 URL 首先。
编辑
我重写了原始片段(仍然可以在编辑历史中找到)。
我将
<image>
标签更改为<use>
。这导致内存使用量小得多。我还添加了 IE11 的回退,它接受将外部图像编码为数据 URL,但仍然无法通过 canvas 将 svg 转换为 png。 回退将用 canvas 替换目标
<img>
标签。后者可以由用户通过右键单击来保存。一些注意事项:
它在 Safari 7 中不起作用,也许在其他过时的 webkit 浏览器中也不起作用。这是一个奇怪的错误,因为它在 localhost 中确实像魅力一样工作,但在任何其他网络上都不会(即使在我的家庭网络上,使用 192.168.xxx)。
IE 9 & IE 10 无法将外部图像转换为数据 URL,CORS 问题。
// What to do with the result (either data URL or directly the canvas if tainted)
var callback = function(d, isTainted) {
if (!isTainted) {
$('#chartImg')[0].src = d;
} else
$('#chartImg')[0].parentNode.replaceChild(d, $('#chartImg')[0]);
};
// The url of the external image (must be cross-origin compliant)
var extURL = 'https://dl.dropboxusercontent.com/s/13dv8vzmrlcmla2/tex2.jpg';
google.load('visualization', '1', {
packages: ['corechart']
})
var encodeCall = getbase64URI.bind(this, extURL, callback);
google.setOnLoadCallback(encodeCall);
// Google Chart part
function drawVisualizationDaily(imgUrl, callback, isTainted) {
var data = google.visualization.arrayToDataTable([
['Daily', 'Sales'],
['Mon', 4],
['Tue', 6],
['Wed', 6],
['Thu', 5],
['Fri', 3],
['Sat', 7],
['Sun', 7]
]);
var chart = new google.visualization.ColumnChart(document.getElementById('visualization'));
chart.draw(data, {
title: "Daily Sales",
width: 500,
height: 400,
hAxis: {
title: "Daily"
}
});
// Link to chart's svg element
var svgNode = chart.ea.querySelector('svg');
// Create a symbol for our image
var symbol = document.createElementNS('http://www.w3.org/2000/svg', 'symbol');
// An svg wrapper to allow size changing with <use>
symbol.setAttributeNS(null, 'viewBox', '0,0,10,10');
symbol.setAttributeNS(null, 'preserveAspectRatio', 'none');
symbol.id = 'background';
// And the actual image, with our encoded image
var img = document.createElementNS('http://www.w3.org/2000/svg', 'image');
img.setAttributeNS(null, 'preserveAspectRatio', 'none');
img.setAttributeNS(null, 'width', '100%');
img.setAttributeNS(null, 'height', '100%');
img.setAttributeNS('http://www.w3.org/1999/xlink', 'href', imgUrl);
symbol.appendChild(img);
svgNode.appendChild(symbol);
var blueRects = $("[fill='#3366cc']");
var max = blueRects.length - 1;
blueRects.each(function(index, element) {
var svgimg = document.createElementNS('http://www.w3.org/2000/svg', 'use');
svgimg.setAttributeNS(null, 'x', element.x.baseVal.value);
svgimg.setAttributeNS(null, 'y', element.y.baseVal.value);
svgimg.setAttributeNS(null, 'width', element.width.baseVal.value);
svgimg.setAttributeNS(null, 'height', element.height.baseVal.value);
svgimg.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#background');
svgNode.appendChild(svgimg);
if (index === max && !isTainted) // no need to call it if we don't have our dataURL encoded images
// a load event would be better but it doesn't fire in IE ...
setTimeout(exportSVG.bind(this, svgNode, callback, isTainted), 200);
});
}
function exportSVG(svgNode, callback, isTainted) {
var svgData = (new XMLSerializer()).serializeToString(svgNode);
var img = new Image();
img.onload = function() {
var canvas = document.createElement('canvas');
canvas.width = svgNode.getAttribute('width');
canvas.height = svgNode.getAttribute('height');
canvas.getContext('2d').drawImage(this, 0, 0);
var data, isTainted;
try {
data = canvas.toDataURL();
} catch (e) {
data = canvas;
isTainted = true;
}
callback(data, isTainted);
}
img.src = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData);
}
// A simple function to convert an images's url to base64 data URL
function getbase64URI(url, callback) {
var img = new Image();
img.crossOrigin = "Anonymous";
img.onload = function() {
var c = document.createElement('canvas');
c.width = this.width;
c.height = this.height;
c.getContext('2d').drawImage(this, 0, 0);
var isTainted;
try {
c.toDataURL();
} catch (e) {
isTainted = true;
}
// if the canvas is tainted, return the url
var output = (isTainted) ? url : c.toDataURL();
drawVisualizationDaily(output, callback, isTainted);
}
img.src = url;
}
svg { border: 1px solid yellow; }
img { border: 1px solid green; }
canvas { border: 1px solid red; }
<script src="http://www.google.com/jsapi?.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="visualization"></div>
Right-click this image to save it:
<br>
<img id="chartImg" />
这个html在反应中工作
<a
href={chart.getImageURI()}
download="chart.png">
getImage
</a>