【问题标题】:Export js/d3 visualisation with linked images [duplicate]使用链接图像导出 js/d3 可视化 [重复]
【发布时间】:2018-05-02 20:28:11
【问题描述】:

我对 D3 很陌生(所以我的问题可能有点无聊),并且正在处理我想导出为 png 的可视化。我正在这样做:http://bl.ocks.org/Rokotyan/0556f8facbaf344507cdc45dc3622177

我在样式等方面遇到了一些问题,但内联样式解决了这个问题。

我现在遇到的问题是我在 SVG 中使用的 png 图像没有出现在我导出到 png 的画布中。

我已经尝试了很多,但没有达到预期的结果。

下面的代码将 png 放到 SVG 上:

svg.selectAll("svg")
     .data(inputdata)
     .enter()
     .append("svg:image")
     .attr("xlink:href", "image_1.png")
     .attr("x", function(d) {
        return (d.X_Coordinate);})
     .attr("y", function(d) {
        return (d.Y_Coordinate);})
    .attr("width", image_width)
    .attr("height", image_height)
     ;

d3.selectAll("svg").attr({'xmlns': 'http://www.w3.org/2000/svg','xmlns:xmlns:xlink': 'http://www.w3.org/1999/xlink'});

【问题讨论】:

  • 也许我不是很清楚。我使用了链接中的示例,我在其中放置了 svg 的代码。除了我想要放置的图像之外,我还放置了其他东西,例如文本框等。除了包含的 png 之外,大多数元素都包含在导出中。这些是由上面定义的

标签: javascript d3.js canvas


【解决方案1】:

您需要对images as base64 进行编码。因此,从this excellent answer 借用一些代码并将其与您的链接示例放在一起:

<!DOCTYPE html>
<html lang="en">

<head>
  <title>How to properly export SVG D3 visualization to PNG or JPEG</title>
  <meta charset="utf-8">
  <script src="https://cdn.rawgit.com/eligrey/canvas-toBlob.js/f1a01896135ab378aa5c0118eadd81da55e698d8/canvas-toBlob.js"></script>
  <script src="https://cdn.rawgit.com/eligrey/FileSaver.js/e9d941381475b5df8b7d7691013401e171014e89/FileSaver.min.js"></script>
  <script src="https://d3js.org/d3.v3.min.js"></script>
  <style type="text/css">
    .blendCircle {
      mix-blend-mode: multiply;
    }
  </style>
</head>

<body>
  <div>
    <button id='saveButton'>Export my D3 visualization to PNG</button>
  </div>
  <script type="text/javascript">
    var width = 200,
      height = 200;

    var svg = d3.select('body').append('svg')
      .attr('width', width)
      .attr('height', height);

    svg
      .append("svg:image")
      .each(function() {
        toDataURL(
          'https://i.imgur.com/1kqZEq2.jpg',
          (dataUrl) => {
            d3.select(this).attr("xlink:href", dataUrl);
          }
        )
      })
      .attr("width", width)
      .attr("height", height);

    function toDataURL(src, callback, outputFormat) {
      var img = new Image();
      img.crossOrigin = 'Anonymous';
      img.onload = function() {
        var canvas = document.createElement('CANVAS');
        var ctx = canvas.getContext('2d');
        var dataURL;
        canvas.height = this.naturalHeight;
        canvas.width = this.naturalWidth;
        ctx.drawImage(this, 0, 0);
        dataURL = canvas.toDataURL(outputFormat);
        callback(dataURL);
      };
      img.src = src;
      if (img.complete || img.complete === undefined) {
        img.src = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw==";
        img.src = src;
      }
    }

    // Set-up the export button
    d3.select('#saveButton').on('click', function() {
      var svgString = getSVGString(svg.node());
      svgString2Image(svgString, 2 * width, 2 * height, 'png', save); // passes Blob and filesize String to the callback

      function save(dataBlob, filesize) {
        saveAs(dataBlob, 'D3 vis exported to PNG.png'); // FileSaver.js function
      }
    });

    // Below are the functions that handle actual exporting:
    // getSVGString ( svgNode ) and svgString2Image( svgString, width, height, format, callback )
    function getSVGString(svgNode) {
      svgNode.setAttribute('xlink', 'http://www.w3.org/1999/xlink');
      var cssStyleText = getCSSStyles(svgNode);
      appendCSS(cssStyleText, svgNode);

      var serializer = new XMLSerializer();
      var svgString = serializer.serializeToString(svgNode);
      svgString = svgString.replace(/(\w+)?:?xlink=/g, 'xmlns:xlink='); // Fix root xlink without namespace
      svgString = svgString.replace(/NS\d+:href/g, 'xlink:href'); // Safari NS namespace fix

      return svgString;

      function getCSSStyles(parentElement) {
        var selectorTextArr = [];

        // Add Parent element Id and Classes to the list
        selectorTextArr.push('#' + parentElement.id);
        for (var c = 0; c < parentElement.classList.length; c++)
          if (!contains('.' + parentElement.classList[c], selectorTextArr))
            selectorTextArr.push('.' + parentElement.classList[c]);

        // Add Children element Ids and Classes to the list
        var nodes = parentElement.getElementsByTagName("*");
        for (var i = 0; i < nodes.length; i++) {
          var id = nodes[i].id;
          if (!contains('#' + id, selectorTextArr))
            selectorTextArr.push('#' + id);

          var classes = nodes[i].classList;
          for (var c = 0; c < classes.length; c++)
            if (!contains('.' + classes[c], selectorTextArr))
              selectorTextArr.push('.' + classes[c]);
        }

        // Extract CSS Rules
        var extractedCSSText = "";
        for (var i = 0; i < document.styleSheets.length; i++) {
          var s = document.styleSheets[i];

          try {
            if (!s.cssRules) continue;
          } catch (e) {
            if (e.name !== 'SecurityError') throw e; // for Firefox
            continue;
          }

          var cssRules = s.cssRules;
          for (var r = 0; r < cssRules.length; r++) {
            if (contains(cssRules[r].selectorText, selectorTextArr))
              extractedCSSText += cssRules[r].cssText;
          }
        }


        return extractedCSSText;

        function contains(str, arr) {
          return arr.indexOf(str) === -1 ? false : true;
        }

      }

      function appendCSS(cssText, element) {
        var styleElement = document.createElement("style");
        styleElement.setAttribute("type", "text/css");
        styleElement.innerHTML = cssText;
        var refNode = element.hasChildNodes() ? element.children[0] : null;
        element.insertBefore(styleElement, refNode);
      }
    }


    function svgString2Image(svgString, width, height, format, callback) {
      var format = format ? format : 'png';

      var imgsrc = 'data:image/svg+xml;base64,' + btoa(unescape(encodeURIComponent(svgString))); // Convert SVG string to data URL

      var canvas = document.createElement("canvas");
      var context = canvas.getContext("2d");

      canvas.width = width;
      canvas.height = height;

      var image = new Image();
      image.onload = function() {
        context.clearRect(0, 0, width, height);
        context.drawImage(image, 0, 0, width, height);

        canvas.toBlob(function(blob) {
          var filesize = Math.round(blob.length / 1024) + ' KB';
          if (callback) callback(blob, filesize);
        });


      };

      image.src = imgsrc;
    }
  </script>
</body>

</html>

【讨论】:

    猜你喜欢
    • 2017-05-17
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2016-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多