I am trying to download a graph that I created with d3.js as an png (Any datatyp would do though), but I am failing gloriously.
I followed various questions on Stackoverflow which address similar issues, but still can't get it to work.
With different solutions I very often run into this error when debugging:
Uncaught TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.
This is my code for my svg-graph:
var data = build
// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 30, left: 100},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// set the ranges
var y = d3.scaleBand()
.range([height, 0])
.padding(0.1);
var x = d3.scaleLinear()
.range([0, width]);
// append the svg object to the body of the page
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3.select(".svg-net-area").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// format the data
data.forEach(function(d) {
d.buildings__net_leased_area = +d.buildings__net_leased_area;
});
// Scale the range of the data in the domains
x.domain([0, d3.max(data, function(d){ return d.buildings__net_leased_area; })])
y.domain(data.map(function(d) { return d.buildings__name; }));
//y.domain([0, d3.max(data, function(d) { return d.buildings__net_leased_area; })]);
// append the rectangles for the bar chart
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
//.attr("x", function(d) { return x(d.buildings__net_leased_area); })
.attr("width", function(d) {return x(d.buildings__net_leased_area); } )
.attr("y", function(d) { return y(d.buildings__name); })
.attr("height", y.bandwidth())
.attr("fill", "#348496");
// add the x Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
svg.append("g")
.call(d3.axisLeft(y));
And this is what I am trying:
function svgDataURL(svg) {
var svgAsXML = (new XMLSerializer).serializeToString(svg);
return "data:image/svg+xml," + encodeURIComponent(svgAsXML);
}
function download(){
var dataURL = svgDataURL(svg)
var dl = document.createElement("a");
document.body.appendChild(dl);
dl.setAttribute("href", dataURL);
dl.setAttribute("download", "test.svg");
dl.click();
}
I call this function in my django template.
I am trying to create a DataURL for my svg graph. Then I want to pass it to the download function. But I am not entirely sure what I am even doing here.
So if someone could help that would be very nice. Thanks in advance.
I am trying to download a graph that I created with d3.js as an png (Any datatyp would do though), but I am failing gloriously.
I followed various questions on Stackoverflow which address similar issues, but still can't get it to work.
With different solutions I very often run into this error when debugging:
Uncaught TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.
This is my code for my svg-graph:
var data = build
// set the dimensions and margins of the graph
var margin = {top: 20, right: 20, bottom: 30, left: 100},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// set the ranges
var y = d3.scaleBand()
.range([height, 0])
.padding(0.1);
var x = d3.scaleLinear()
.range([0, width]);
// append the svg object to the body of the page
// append a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3.select(".svg-net-area").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
// format the data
data.forEach(function(d) {
d.buildings__net_leased_area = +d.buildings__net_leased_area;
});
// Scale the range of the data in the domains
x.domain([0, d3.max(data, function(d){ return d.buildings__net_leased_area; })])
y.domain(data.map(function(d) { return d.buildings__name; }));
//y.domain([0, d3.max(data, function(d) { return d.buildings__net_leased_area; })]);
// append the rectangles for the bar chart
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
//.attr("x", function(d) { return x(d.buildings__net_leased_area); })
.attr("width", function(d) {return x(d.buildings__net_leased_area); } )
.attr("y", function(d) { return y(d.buildings__name); })
.attr("height", y.bandwidth())
.attr("fill", "#348496");
// add the x Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
// add the y Axis
svg.append("g")
.call(d3.axisLeft(y));
And this is what I am trying:
function svgDataURL(svg) {
var svgAsXML = (new XMLSerializer).serializeToString(svg);
return "data:image/svg+xml," + encodeURIComponent(svgAsXML);
}
function download(){
var dataURL = svgDataURL(svg)
var dl = document.createElement("a");
document.body.appendChild(dl);
dl.setAttribute("href", dataURL);
dl.setAttribute("download", "test.svg");
dl.click();
}
I call this function in my django template.
I am trying to create a DataURL for my svg graph. Then I want to pass it to the download function. But I am not entirely sure what I am even doing here.
So if someone could help that would be very nice. Thanks in advance.
Share edited Jun 25, 2019 at 9:31 Matt Ellen 11.6k4 gold badges72 silver badges93 bronze badges asked Jun 25, 2019 at 9:29 MicromegasMicromegas 1,6994 gold badges23 silver badges57 bronze badges1 Answer
Reset to default 4In your code, svg
is a D3 selection. You cannot pass a D3 selection to serializeToString
. Have a look at the error here:
var svg = d3.select("svg");
var svgAsXML = (new XMLSerializer).serializeToString(svg);
console.log(svgAsXML)
<script src="https://cdnjs.cloudflare./ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
<circle r="20" cx="100" cy="50"></circle>
</svg>
As you can see, serializeToString
requires a node:
The Node to use as the root of the DOM tree or subtree for which to construct an XML representation.
Therefore, instead of passing a D3 selection, you have to pass the node. The easiest way to do that is using the D3 method node()
on the selection:
var svg = d3.select("svg");
var svgAsXML = (new XMLSerializer).serializeToString(svg.node());
console.log(svgAsXML)
<script src="https://cdnjs.cloudflare./ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
<circle r="20" cx="100" cy="50"></circle>
</svg>
So, in your code, pass the node to the svgDataUrl
function:
var dataURL = svgDataURL(svg.node())
Alternatively, pass the D3 selection to svgDataUrl
, but use the node inside serializeToString
, as I did above.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744883438a4598977.html
评论列表(0条)