2015-09-17 36 views
0

我正在嘗試使用動態運輸數據使用d3 sankey plugin創建sankey圖表。它的偉大工程的大部分時間除了當我得到一個數據集是這樣的:防止在D3js Sankey圖表中循環

[{"DeparturePort":"CHARLESTON","ArrivalPort":"BREMERHAVEN","volume":5625.74},{"DeparturePort":"CHARLESTON","ArrivalPort":"ITAPOA","volume":2340},{"DeparturePort":"PT EVERGLADES","ArrivalPort":"PT AU PRINCE","volume":41.02},{"DeparturePort":"BREMERHAVEN","ArrivalPort":"CHARLESTON","volume":28}] 

我的問題的關鍵是數據集中的第一個和最後一個條目。似乎在相同的sankey圖表中有相反的方向將JavaScript發送到無限循環並殺死瀏覽器。有關如何防止這種情況發生的任何想法?

這裏是我的圖表代碼,其中原料是上面的對象:

var data = raw; 
       var units = "Volume"; 

       var margin = { top: 100, right: 0, bottom: 30, left: 0 }, 
        width = $("#"+divID).width() - margin.left - margin.right, 
        height = divID == "enlargeChart" ? 800 - margin.top - margin.bottom : 600 - margin.top - margin.bottom; 

       var formatNumber = d3.format(",.0f"), // zero decimal places 
        format = function (d) { return ""; }, 
        color = d3.scale.ordinal() 
        .range(["#0077c0", "#FF6600"]); 

       // append the svg canvas to the page 
       var svg = d3.select("#"+divID).append("svg") 
        .attr("width", width + margin.left + margin.right) 
        .attr("height", height + margin.top + margin.bottom) 
        .style("font-size", "12px") 
        .append("g") 
        .attr("transform", 
          "translate(" + margin.left + "," + margin.top + ")"); 

       // Set the sankey diagram properties 
       var sankey = d3.sankey(width) 
        .nodeWidth(10) 
        .nodePadding(10) 
        .size([width, height]); 

       var path = sankey.link(); 
       // load the data (using the timelyportfolio csv method) 
       //d3.csv("sankey.csv", function (error, data) { 

        //set up graph in same style as original example but empty 
        graph = { "nodes": [], "links": [] }; 
        var checklist = []; 
        data.forEach(function (d) { 
         if ($.inArray(d.DeparturePort, checklist) == -1) { 
          checklist.push(d.DeparturePort) 
          graph.nodes.push({ "name": d.DeparturePort }); 
         } 
         if ($.inArray(d.ArrivalPort, checklist) == -1) { 
          checklist.push(d.ArrivalPort) 
          graph.nodes.push({ "name": d.ArrivalPort }); 
         } 
         graph.links.push({ 
          "source": d.DeparturePort, 
          "target": d.ArrivalPort, 
          "value": +d.volume 
         }); 
        }); 

        // return only the distinct/unique nodes 
        graph.nodes = d3.keys(d3.nest() 
         .key(function (d) { return d.name; }) 
         .map(graph.nodes)); 

        // loop through each link replacing the text with its index from node 
        graph.links.forEach(function (d, i) { 
         graph.links[i].source = graph.nodes.indexOf(graph.links[i].source); 
         graph.links[i].target = graph.nodes.indexOf(graph.links[i].target); 
        }); 

        //now loop through each nodes to make nodes an array of objects 
        // rather than an array of strings 
        graph.nodes.forEach(function (d, i) { 
         graph.nodes[i] = { "name": d }; 
        }); 


        sankey 
         .nodes(graph.nodes) 
         .links(graph.links) 
         .layout(32); 

        // add in the links 
        var link = svg.append("g").selectAll(".link") 
         .data(graph.links) 
         .enter().append("path") 
         .attr("class", "link") 
         .attr("d", path) 
         .style("stroke-width", function (d) { return Math.max(1, d.dy); }) 
         .sort(function (a, b) { setTimeout(function() { return b.dy - a.dy; }, 10);}); 

        // add the link titles 
        link.append("title") 
          .text(function (d) { 
          return d.source.name + " → " + 
           d.target.name + "\n" + d.value.toFixed(0) + " TEU"; 
          }); 
        $("#" + divID + " .loading").addClass("hide"); 


        // add in the nodes 
        var node = svg.append("g").selectAll(".node") 
         .data(graph.nodes) 
         .enter().append("g") 
         .attr("class", "node") 
         .attr("transform", function (d) { 
           //setTimeout(function() { 
          return "translate(" + d.x + "," + d.y + ")"; 
           //}, 10); 
         }) 
         .call(d3.behavior.drag() 
         .origin(function (d) { return d; }) 
         .on("dragstart", function() { 
          this.parentNode.appendChild(this); 
         }) 
         .on("drag", dragmove)); 

        // add the rectangles for the nodes 
        node.append("rect") 
         .attr("height", function (d) { if (d.dy < 0) { d.dy = (d.dy * -1); } return d.dy; }) 
         .attr("width", sankey.nodeWidth()) 
         .style("fill", function (d) { 
          return d.color = color(d.name); 
         }) 
         .style("stroke", function (d) { 
          return d3.rgb(d.color); 
         }) 
         .append("title") 
         .text(function (d) { 
          return d.name + "\n" + format(d.value); 
         }); 
        // add in the title for the nodes 
        node.append("text") 
         .attr("x", -6) 
         .attr("y", function (d) { return d.dy/2; }) 
         .attr("dy", ".35em") 
         .attr("text-anchor", "end") 
        .style("stroke", function (d) { return "#000000" }) 
         .attr("transform", null) 
         .text(function (d) { return d.name; }) 
         .filter(function (d) { return d.x < width/2; }) 
         .attr("x", 6 + sankey.nodeWidth()) 
         .attr("text-anchor", "start"); 

        // the function for moving the nodes 
        function dragmove(d) { 
         d3.select(this).attr("transform", 
          "translate(" + d.x + "," + (
            d.y = Math.max(0, Math.min(height - d.dy, d3.event.y)) 
           ) + ")"); 
         sankey.relayout(); 
         link.attr("d", path); 
        } 
      }, 0) 
+0

你希望代碼在這種情況下做什麼?您可以在繪製圖表之前驗證數據嗎? – Gildor

+0

理想情況下,他們會加在一起,但我會很高興只是完全跳過第二個,只是爲了避免瀏覽器崩潰。 – AOndracek

回答