Uncaught TypeError: Не удалось выполнить 'serializeToString' на 'XMLSerializer': Не удалось загрузить SVG (созданный с помощью D3.js) в формате png / pdf - PullRequest
2 голосов
/ 25 июня 2019

Я пытаюсь загрузить график, который я создал с помощью d3.js, в качестве png (любой тип данных подойдет), но у меня ничего не получается.

Я следил за различными вопросами по Stackoverflow, которые касаются подобных проблем, но все еще не могу заставить его работать.

С различными решениями я очень часто сталкиваюсь с этой ошибкой при отладке:

Uncaught TypeError: Не удалось выполнить 'serializeToString' для 'XMLSerializer': параметр 1 не относится к типу 'Node'.

Это мой код для моего svg-графа:

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));

И вот что я пытаюсь:

 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();
      }

Я называю этофункция в моем шаблоне Django.

Я пытаюсь создать DataURL для моего графика SVG.Затем я хочу передать его в функцию загрузки.Но я не совсем уверен, что я здесь делаю.

Так что, если кто-то может помочь, было бы очень хорошо.Заранее спасибо.

1 Ответ

3 голосов
/ 25 июня 2019

В вашем коде svg - это выбор D3 .Вы не можете передать выбор D3 на serializeToString.Посмотрите на ошибку здесь:

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>

Как видите, serializeToString требуется узел:

Узел для использования в качествекорень дерева DOM или поддерева, для которого нужно построить представление XML.

Поэтому, вместо передачи выбора D3, вы должны пропустить узел.Самый простой способ сделать это - использовать метод 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>

Итак, в своем коде передайте узел функции svgDataUrl:

var dataURL = svgDataURL(svg.node())

В качестве альтернативы передайте выбор D3 вsvgDataUrl, но используйте узел внутри serializeToString, как я делал выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...