2016-04-29 9 views
1

Ich habe ein mehrzeiliges Diagramm erstellt, aber ich habe mich bemüht, ein Voronoi für bessere Mausinteraktionen hinzuzufügen. Jede Hilfe, um mich in die richtige Richtung zu lenken, würde sehr geschätzt werden.d3 multiline voronoi funktioniert nicht

Hier ist meine Daten:

U.S. Custom Ports,Coast,Year,Value 
"Aberdeen, WA",P,1997,0 
"Aberdeen, WA",P,1998,24 
"Aberdeen, WA",P,1999,3284.95 
"Aberdeen, WA",P,2000,0 
"Aberdeen, WA",P,2001,78.83 
"Aberdeen, WA",P,2002,75.16 
"Aberdeen, WA",P,2003,0 
"Aberdeen, WA",P,2004,0 
"Aberdeen, WA",P,2005,194.35 
"Aberdeen, WA",P,2006,0 
"Aberdeen, WA",P,2007,0 
"Aberdeen, WA",P,2008,0 
"Aberdeen, WA",P,2009,45.14 
"Aberdeen, WA",P,2010,303 
"Aberdeen, WA",P,2011,680.42 
"Aberdeen, WA",P,2012,437.43 
"Aberdeen, WA",P,2013,2436.97 
"Aberdeen, WA",P,2014,894.86 
"Anacortes, WA",P,1997,0 
"Anacortes, WA",P,1998,0 
"Anacortes, WA",P,1999,0 
"Anacortes, WA",P,2000,0 
"Anacortes, WA",P,2001,0 
"Anacortes, WA",P,2002,0 
"Anacortes, WA",P,2003,0 
"Anacortes, WA",P,2004,0 
"Anacortes, WA",P,2005,0 

Hier ist mein Code:

function drawMultiLine(){ 

     var container = d3.select('#g-multiline'); 

     var margin = {top:10, right: 80, bottom: 30, left: 30}, 
     width = 300 - margin.left - margin.right, 
     height = 550 - margin.top - margin.bottom; 

     var parseYear = d3.time.format("%Y").parse; 


     var x = d3.time.scale().range([0, width]); 
     var y = d3.scale.linear().range([height, 0]); 

     var xAxis = d3.svg.axis().scale(x) 
      .orient("bottom") 
      .ticks(2) 

     var yAxis = d3.svg.axis().scale(y) 
      .orient("right").ticks(4) 

     var valueline = d3.svg.line() 
     // .interpolate("basis") 
     .interpolate("step-before") 
     .x(function(d) { return x(d.Year); }) 
     .y(function(d) { return y(d.Value); }); 

     var g = container 
     .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 + ")"); 

     function make_x_axis() { return d3.svg.axis() 
     .scale(x) 
     .orient("bottom") 
     .ticks(5) 
     } 
     function make_y_axis() { return d3.svg.axis() 
     .scale(y) 
     .orient("left") 
     .ticks(10) 
     } 

     var voronoi = d3.geom.voronoi() 
     .x(function(d) { return x(d.Year); }) 
     .y(function(d) { return y(d.Value); }) 
     .clipExtent([[-margin.left, -margin.top], [width + margin.right, height + margin.bottom]]); 

     d3.csv("../../data/container_data.csv", function(error,data){ 
     if (error) throw error; 

     data.forEach(function(d) { 
      d.Year = parseYear(d.Year); 
      d.Value = +d.Value; 
     }); 

     x.domain(d3.extent(data, function(d) { return d.Year; })); 
     y.domain([0, d3.max(data, function(d) { return d.Value; })]); 

     g.append("g") 
      .attr("class", "xgrid") 
      .attr("transform", "translate(0," + height + ")") 
      .call(make_x_axis() 
       .tickSize(-height, 0, 0) 

     ) 
     g.append("g") 
      .attr("class", "ygrid") 
      .call(make_y_axis() 
       .tickSize(-width, 0, 0) 
       .ticks(5) 
       .tickFormat(d3.format("s")) 
     ) 

     g.append("g")   // Add the X Axis 
      .attr("class", "x axis") 
      .attr("transform", "translate(0," + height + ")") 
      .call(xAxis); 

     g.append("g")   // Add the Y Axis 
      .attr("class", "y axis") 
      .call(yAxis) 
      .append("text") 
      .attr("y", 80) 
      .attr("dy", ".71em") 
      .style("text-anchor", "end") 
      .text("Tons"); 


     // Nest the entries by port name 
     var dataNest = d3.nest() 
      .key(function(d){return d["U.S. Custom Ports"]}) 
      .entries(data); 

     g.append("rect") 
       .attr("x", 110) 
       .attr("y", 0) 
       .attr("width", "5%") 
       .attr("height", height) 
       .attr("class","recession") 

     dataNest 
      .forEach(function(d) { 
      g.append("path") 
       .attr("class", "line") 
       .attr("d", valueline(d.values)) 
       // .attr("class",d.key, "line") 
     }); 

     var focus = g.append("g") 
      .attr("class", "focus") 
      .attr("transform", "translate(-100,-100)"); 

     focus.append("circle") 
      .attr("r", 4); 

     var voronoiGroup = g.append("g") 
      .attr("class", "voronoi"); 

     voronoiGroup.selectAll("path") 
      .data(voronoi(dataNest)) 
      .enter().append("path") 
      .attr("d", function(d) { return "M" + d.join("L") + "Z"; }) 
      .datum(function(d) { return d.point; }) 


     }) 
    } 

drawMultiLine(); 

Antwort

0

Sie passieren die voronoi Funktion eine Reihe von verschachtelten Objekten. Dies ist falsch, da es expecting a flat array of data ist. Die einfachste Fix Ihre heißt abzuflachen:

var vd = []; 
dataNest.forEach(function(d){ 
    vd = vd.concat(d.values); 
}); 

voronoiGroup.selectAll("path") 
    .data(voronoi(vd)) 
    .enter().append("path") 
    .attr("d", function(d) { 
    if (d) return "M" + d.join("L") + "Z"; 
    }) 
    .datum(function(d) { 
     if (d) return d.point; 
    }); 

Arbeitscode:

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script> 
 
    <style> 
 
    path { 
 
     fill: none; 
 
     stroke: steelblue; 
 
    } 
 
    
 
    rect { 
 
     fill: orange; 
 
    } 
 
    
 
    .voronoi path { 
 
    fill: none; 
 
    pointer-events: all; 
 
} 
 
    </style> 
 
</head> 
 

 
<body> 
 
    <div id="g-multiline"></div> 
 
    <script> 
 
    function drawMultiLine() { 
 

 
     var container = d3.select('#g-multiline'); 
 

 
     var margin = { 
 
      top: 10, 
 
      right: 80, 
 
      bottom: 30, 
 
      left: 30 
 
     }, 
 
     width = 500 - margin.left - margin.right, 
 
     height = 550 - margin.top - margin.bottom; 
 

 
     var parseYear = d3.time.format("%Y").parse; 
 

 

 
     var x = d3.time.scale().range([0, width]); 
 
     var y = d3.scale.linear().range([height, 0]); 
 

 
     var xAxis = d3.svg.axis().scale(x) 
 
     .orient("bottom") 
 
     .ticks(2) 
 

 
     var yAxis = d3.svg.axis().scale(y) 
 
     .orient("right").ticks(4) 
 

 
     var valueline = d3.svg.line() 
 
     // .interpolate("basis") 
 
     .interpolate("step-before") 
 
     .x(function(d) { 
 
      return x(d.Year); 
 
     }) 
 
     .y(function(d) { 
 
      return y(d.Value); 
 
     }); 
 

 
     var g = container 
 
     .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 + ")"); 
 

 
     function make_x_axis() { 
 
     return d3.svg.axis() 
 
      .scale(x) 
 
      .orient("bottom") 
 
      .ticks(5) 
 
     } 
 

 
     function make_y_axis() { 
 
     return d3.svg.axis() 
 
      .scale(y) 
 
      .orient("left") 
 
      .ticks(10) 
 
     } 
 

 
     var voronoi = d3.geom.voronoi() 
 
     .x(function(d) { 
 
      return x(d.Year); 
 
     }) 
 
     .y(function(d) { 
 
      return y(d.Value); 
 
     }) 
 
     .clipExtent([ 
 
      [-margin.left, -margin.top], 
 
      [width + margin.right, height + margin.bottom] 
 
     ]); 
 

 
     //d3.csv("data.csv", function(error, data) { 
 
     var data = [{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"1997","Value":"0"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"1998","Value":"24"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"1999","Value":"3284.95"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2000","Value":"0"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2001","Value":"78.83"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2002","Value":"75.16"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2003","Value":"0"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2004","Value":"0"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2005","Value":"194.35"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2006","Value":"0"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2007","Value":"0"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2008","Value":"0"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2009","Value":"45.14"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2010","Value":"303"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2011","Value":"680.42"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2012","Value":"437.43"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2013","Value":"2436.97"},{"U.S. Custom Ports":"Aberdeen, WA","Coast":"P","Year":"2014","Value":"894.86"},{"U.S. Custom Ports":"Anacortes, WA","Coast":"P","Year":"1997","Value":"0"},{"U.S. Custom Ports":"Anacortes, WA","Coast":"P","Year":"1998","Value":"0"},{"U.S. Custom Ports":"Anacortes, WA","Coast":"P","Year":"1999","Value":"0"},{"U.S. Custom Ports":"Anacortes, WA","Coast":"P","Year":"2000","Value":"0"},{"U.S. Custom Ports":"Anacortes, WA","Coast":"P","Year":"2001","Value":"0"},{"U.S. Custom Ports":"Anacortes, WA","Coast":"P","Year":"2002","Value":"0"},{"U.S. Custom Ports":"Anacortes, WA","Coast":"P","Year":"2003","Value":"0"},{"U.S. Custom Ports":"Anacortes, WA","Coast":"P","Year":"2004","Value":"0"},{"U.S. Custom Ports":"Anacortes, WA","Coast":"P","Year":"2005","Value":"0"}]; 
 

 
     data.forEach(function(d) { 
 
      d.Year = parseYear(d.Year); 
 
      d.Value = +d.Value; 
 
     }); 
 

 
     x.domain(d3.extent(data, function(d) { 
 
      return d.Year; 
 
     })); 
 
     y.domain([0, d3.max(data, function(d) { 
 
      return d.Value; 
 
     })]); 
 

 
     g.append("g") 
 
      .attr("class", "xgrid") 
 
      .attr("transform", "translate(0," + height + ")") 
 
      .call(make_x_axis() 
 
      .tickSize(-height, 0, 0) 
 

 
     ) 
 
     g.append("g") 
 
      .attr("class", "ygrid") 
 
      .call(make_y_axis() 
 
      .tickSize(-width, 0, 0) 
 
      .ticks(5) 
 
      .tickFormat(d3.format("s")) 
 
     ) 
 

 
     g.append("g") // Add the X Axis 
 
      .attr("class", "x axis") 
 
      .attr("transform", "translate(0," + height + ")") 
 
      .call(xAxis); 
 

 
     g.append("g") // Add the Y Axis 
 
      .attr("class", "y axis") 
 
      .call(yAxis) 
 
      .append("text") 
 
      .attr("y", 80) 
 
      .attr("dy", ".71em") 
 
      .style("text-anchor", "end") 
 
      .text("Tons"); 
 

 

 
     // Nest the entries by port name 
 
     var dataNest = d3.nest() 
 
      .key(function(d) { 
 
      return d["U.S. Custom Ports"] 
 
      }) 
 
      .entries(data); 
 

 
     g.append("rect") 
 
      .attr("x", 110) 
 
      .attr("y", 0) 
 
      .attr("width", "5%") 
 
      .attr("height", height) 
 
      .attr("class", "recession") 
 

 
     dataNest 
 
      .forEach(function(d) { 
 
      g.append("path") 
 
       .attr("class", "line") 
 
       .attr("d", valueline(d.values)) 
 
       .attr("id", d.key.replace(/, /, '')) 
 
      }); 
 

 
     var focus = g.append("g") 
 
      .attr("class", "focus") 
 
      .attr("transform", "translate(-100,-100)"); 
 

 
     focus.append("circle") 
 
      .attr("r", 4); 
 

 
     var voronoiGroup = g.append("g") 
 
      .attr("class", "voronoi"); 
 
     
 
     var vd = []; 
 
     dataNest.forEach(function(d){ 
 
      console.log(d); 
 
      vd = vd.concat(d.values); 
 
     }) 
 

 
     voronoiGroup.selectAll("path") 
 
      .data(voronoi(vd)) 
 
      .enter().append("path") 
 
      .attr("d", function(d) { 
 
      if (d) return "M" + d.join("L") + "Z"; 
 
      }) 
 
      .datum(function(d) { 
 
      if (d) return d.point; 
 
      }) 
 
      .on("mouseover", function(d){ 
 
      var key = d["U.S. Custom Ports"].replace(/, /,''); 
 
      d3.select('#' + key) 
 
       .style("stroke", "green"); 
 
      }) 
 
      .on("mouseout", function(d){ 
 
      var key = d["U.S. Custom Ports"].replace(/, /,''); 
 
      d3.select('#' + key) 
 
       .style("stroke", "steelblue"); 
 
      }) 
 

 

 
    // }) 
 
    } 
 

 
    drawMultiLine(); 
 
    </script> 
 
</body> 
 

 
</html>

+0

Whoa, dank Mark, das ist super hilfsbereit. Ich habe eine kurze Frage, ich versuche, mouseover/mouseout Funktionen hinzuzufügen, um Linienfarbe zu ändern ..... Aber bis jetzt habe ich kein Glück, mouseover zu machen, um meinen Linien zu entsprechen. Ich bin mir ziemlich sicher, dass meine d3-Auswahl das Problem verursacht, aber ich bin mir nicht sicher, wie ich das beheben soll. – fabrice

+0

@fabrice, siehe Aktualisierungen des obigen Code-Snippets. – Mark

+0

Es tut mir leid, dass ich Sie wieder abgehört habe. Ich habe das Schnipsel oben ermüdet, hatte aber immer noch kein Glück, wenn ich schweben konnte. Ich bin so verwirrt. Ich habe meinen Code auf bl.ocks hochgeladen, es wäre extrem hilfreich, wenn Sie mich bitte in die richtige Richtung leiten könnten: http://blockbuilder.org/jeremycflin/a304ed19652fee4cfbe58bc9c0afa2ec – fabrice