如何渲染d3图表,将其导出为图像,然后加载下一个数据集,绘制下一个图表并再次导出

时间:2017-03-08 14:11:43

标签: javascript jquery asp.net d3.js svg

我正在建立一个医疗应用程序,我必须向某个部门的某些人显示受伤。我正在使用d3在我追踪的svg插图上标记受伤区域。例如,如果有人手臂上有溢出物,svg图形会显示手臂呈红色。我设法做了这个部分并编写了一个函数来将svg导出为图像并将其显示在div中的同一屏幕上,作为缩略图。

我的目标是让用户选择一个部门,我需要为该部门中的每个人渲染一个svg地图,并在div标签内显示缩略图,以便他们可以直观地看到正在进行的事情。

我的数据集采用以下格式:x1,x2,x3 ... | y1,y2,y3 ... | ...其中x是为人X和y点亮红色的svg的id另一个人的ids Y。

示例:boneID_043,boneID_046,boneID_038,boneID_029,boneID_027 | boneID_043,boneID_046,boneID_038,boneID_029,boneID_027

我设计的方式是:

  1. 从SQL查询加载数据集
  2. 使用d3
  3. 将第一个数据组加载到SVG中
  4. 在div标签#diagram中渲染SVG,该标签设置为display:none;
  5. 运行导出功能以制作图像blob并在新div中显示
  6. 从数据集加载下一个数据组并重复
  7. 这是在为一个人跑步并点击我的导出到图像按钮后的样子,该按钮调用函数exportD3();

    injury map

    编辑:道歉,我忘记输出当前结果。对于2个人的数据组,这是我在代码运行后看到的内容。有一个指向blob文件的链接,因此导出确实创建了一个图像blob如果我单击我的手动导出按钮,它会正确导出第二人的数据,如上所示。

    [blank map

    我的问题是在回发后(通过在c#/ asp.net中执行查询的按钮来获取数据并将其发布到div中)我尝试循环上面的数据集并使用这些ID加载SVG ,然后运行我的导出功能,但我只看到空白图像,就好像导出在加载svg之前运行。但是在回发后如果我点击我的导出按钮,它会导出最新的svg和最后一个数据(在这种情况下为y)。

    我无法弄清楚为什么导出不能通过代码工作。有没有办法让javascript等待渲染完成,然后导出例如这可能是一个并发问题?我认为这是因为#diagram div(渲染发生的地方)被隐藏但是当我按下我的手动按钮时它确实有效。我也尝试将exportD3()中的导出代码复制并粘贴到for循环中但不起作用

    这是我的代码:

    假设:

    1. 一个名为#diagram的div标签,用于在每次渲染期间保存svg

    2. combined.json是我的人体svg插图文件

    3. imgSVG是一个div标签,每当我们向其添加新图像时,它将包含带有缩略图图像blob的多个div

    4. bArray包含受影响的骨骼,fArray包含肉体/表面伤害,它们总是具有相同的长度

      var bArray = document.getElementById("     <%=boneIds.ClientID%>").innerHTML.split('|');
      var fArray = document.getElementById("<%=bodyPartsIds.ClientID%>").innerHTML.split('|');
      
      var width = 720, height = 720;
      
      svg = d3.select("#diagram").append("svg")
      .attr("width", width)
      .attr("height", height)
      .call(d3.behavior.zoom()
      .on("zoom", redraw))
      .append("g")
      .attr("transform", "translate(5.1261,2)scale(0.4152752)"); //15.1261,-38.639
      
    5. 现在我想循环遍历数据集中的数据组,加载svg并导出到缩略图中并将每个内容附加到#imgSVG div

      for(var i = 0; i < bArray.Length; i++) 
          {
      //Split the data by comma
      d3.json("data/combined.json", function (data) {
                  svg.selectAll("polygon")
                      .data(data.Polygons)
                      .enter().append("polygon")
                      .attr("points", function (d) { //logic here }
                      .attr("fill", function (d) { //logic here };
      
          //Then export to image blob
          exportD3();
      }
      
       function exportD3()
          {
              //This function xports the d3 figures to a div tag
              var doctype = '<?xml version="1.0" standalone="no"?>'
                  + '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';
      
              // serialize the SVG to a string.
              var source = (new XMLSerializer()).serializeToString(d3.select('svg').node());
      
              // create a file blob
              var blob = new Blob([doctype + source], { type: 'image/svg+xml;charset=utf-8' });
      
              var url = window.URL.createObjectURL(blob);
      
              //Next line just shows the parts affected
              var info2 = "<h3>" + document.getElementById("<%=nameInfo.ClientID%>").innerText + "</h3><br/><b>Bones Affected:</b><br />" + boneParts.join(", ") + "<br/><br/><b>Surface Parts Affected:</b><br />" + bParts.join(", ");
      
      
              var img = d3.select('#imgSVG').append("div")
                  .attr('class', 'divs')
                  .style("opacity", 1)
                  .style('width', '300px')
                  .style('height', '400px')
                  .style('float', 'left')
              .html(info)
                  .append('img')
                   .attr('width', 300)
                   .attr('height', 300)
                   .node();
      
              img.src = url;
          }
      

1 个答案:

答案 0 :(得分:0)

我认为任何人都有相同的情况。

似乎在for循环中使用d3.json代码块将无法正常工作,因为它会等待循环完成并发生一些奇怪的事情。

相反,我在d3块中添加了for循环,并以这种方式遍历我的变量。

d3.json("data/combined.json", function (data) {

        for(var i = 0; i < max; i++)
        {