2016-04-29 4 views
1

Я создал многострочный график, но я изо всех сил пытался добавить voronoi для улучшения взаимодействия с мышью. Любая помощь, чтобы указать мне в правильном направлении, будет очень признательна.d3 multiline voronoi не работает

Вот мои данные:

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 

Вот мой код:

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

ответ

0

Вы пропусканием voronoi функцию массив из вложенных объектов. Это неверно, так как это expecting a flat array of data. Самым простым способом исправить, чтобы сгладить ваш есть:

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

Рабочий код:

<!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

Вау, спасибо Марк, это супер полезно. У меня есть один быстрый вопрос, я пытаюсь добавить функции mouseover/mouseout для изменения цвета линии ..... Но до сих пор мне не повезло, что мы наводили указатель мыши на мои строки. Я уверен, что это мой выбор d3, который вызывает проблему, но я не уверен, как это исправить. – fabrice

+0

@fabrice, см. Обновления фрагмента кода выше. – Mark

+0

так сожалею о том, что снова тебя пробовали. Я устал от фрагмента выше, но мне все равно не повезло, что наведите цвет на работу. Я так смущен. Я загрузил свой код в bl.ocks, было бы очень полезно, если бы вы могли направлять меня в правильном направлении: http://blockbuilder.org/jeremycflin/a304ed19652fee4cfbe58bc9c0afa2ec – fabrice

Смежные вопросы