简体   繁体   English

未捕获的TypeError:无法在'XMLSerializer'上执行'serializeToString':未能下载svg(使用D3.js创建)为png / pdf

[英]Uncaught TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': Failing to download an svg (created with D3.js) as png/pdf

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. 我正在尝试下载使用d3.js创建的图形作为png(尽管任何datatyp都会这样做),但是我却光荣地失败了。

I followed various questions on Stackoverflow which address similar issues, but still can't get it to work. 我在Stackoverflow上关注了多个问题,这些问题解决了类似的问题,但仍然无法使它正常工作。

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'. 未捕获到的TypeError:无法在“ XMLSerializer”上执行“ serializeToString”:参数1的类型不是“节点”。

This is my code for my svg-graph: 这是我的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. 我在Django模板中调用此函数。

I am trying to create a DataURL for my svg graph. 我正在尝试为我的svg图创建一个DataURL。 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. 提前致谢。

In your code, svg is a D3 selection . 在您的代码中, svgD3选择 You cannot pass a D3 selection to serializeToString . 您不能将D3选择传递给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.com/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: 如您所见, serializeToString需要一个节点:

The Node to use as the root of the DOM tree or subtree for which to construct an XML representation. 要用作为其构建XML表示形式的DOM树或子树的根的节点。

Therefore, instead of passing a D3 selection, you have to pass the node. 因此,您不必传递D3选择,而必须传递节点。 The easiest way to do that is using the D3 method node() on the selection: 最简单的方法是在选择项上使用D3方法node()

 var svg = d3.select("svg"); var svgAsXML = (new XMLSerializer).serializeToString(svg.node()); console.log(svgAsXML) 
 <script src="https://cdnjs.cloudflare.com/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: 因此,在您的代码中,将该节点传递给svgDataUrl函数:

var dataURL = svgDataURL(svg.node())

Alternatively, pass the D3 selection to svgDataUrl , but use the node inside serializeToString , as I did above. 或者,将D3选择传递给svgDataUrl ,但像上面svgDataUrl ,使用serializeToString内部的节点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM