2016-06-19 8 views
1

私はd3.jsでインタラクティブな線図を作成しようとしています。私は2つのcsvファイル(emissions.csvとgdp.csv)からデータを取得しています。グラフ上にマウスを置くと、ライン上の対応する点に関する情報が表示されます。今私はラベルを表示するためにライン上でマウスを渡す必要があり、私は何をしたいのかを理解することができません。私はthisの例を見出しましたが、私が望むものを示していますが、コードラインのいくつかを理解することはできません。私はそれをどのように私のグラフに使用するのか理解できません。
ここに私のコード:d3.jsを使用したインタラクティブな線グラフ

<!DOCTYPE html> 
<meta charset="utf-8"> 
<style> 

body { 
    font: 10px sans-serif; 
} 

.axis path, 
.axis line { 
    fill: none; 
    stroke: #000; 
    shape-rendering: crispEdges; 
} 

.x.axis path { 
    /*display: none;*/ 
} 

.line { 
    fill: none; 
    stroke: steelblue; 
    stroke-width: 1.5px; 
} 

</style> 
<body> 
    <script data-require="[email protected]" data-semver="3.5.3" src="//cdnjs.cloudflare.com/ajax/libs/d3/3.5.3/d3.js"></script> 
<script> 

var margin = {top: 20, right: 80, bottom: 30, left: 150}, 
    width = 960 - margin.left - margin.right, 
    height = 500 - margin.top - margin.bottom; 

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

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

var color = d3.scale.category10(); 

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

var yAxis = d3.svg.axis() 
    .scale(y) 
    .orient("left"); 

var line = d3.svg.line() 
    //.interpolate("basis") 
    .x(function(d) { return x(d.year); }) 
    .y(function(d) { return y(d.emission); }); 

var svg = d3.select("body").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 + ")"); 

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

    color.domain(d3.keys(data[0]).filter(function(key) { return key !== "year"; })); 

    var cities = color.domain().map(function(name) { 
    return { 
     name: name, 
     values: data.map(function(d) { 
     return {year: d.year, emission: +d[name]}; 
     }) 
    }; 
    }); 

    x.domain(d3.extent(data, function(d) { return d.year; })); 

    y.domain([ 
    0, 
    d3.max(cities, function(c) { return d3.max(c.values, function(v) { return v.emission; }); }) 
    ]); 

    svg.append("g") 
     .attr("class", "x axis") 
     .attr("transform", "translate(0," + height + ")") 
     .call(xAxis); 

    svg.append("g") 
     .attr("class", "y axis") 
     .call(yAxis) 
    .append("text") 
     .attr("transform", "rotate(-90)") 
     .attr("y", 6) 
     .attr("dy", ".71em") 
     .style("text-anchor", "end") 
     .text("Emission (thousand metric tons of CO2)"); 

    var city = svg.selectAll(".city") 
     .data(cities) 
    .enter().append("g") 
     .attr("class", "city"); 


       city.append("path") 
     .attr("class", "line") 
     .attr("d", function(d) { 
     return line(d.values); 
     }) 
     .style("stroke", function(d) { 
     return color(d.name); 
     }); 

    city.append("text") 
     .datum(function(d) { 
     return { 
      name: d.name, 
      value: d.values[d.values.length - 1] 
     }; 
     }) 
     .attr("transform", function(d) { 
     return "translate(" + x(d.value.year) + "," + y(d.value.emission) + ")"; 
     }) 
     .attr("x", 3) 
     .attr("dy", ".35em") 
     .text(function(d) { 
     return d.name; 
     }); 

    var mouseG = svg.append("g") 
     .attr("class", "mouse-over-effects"); 

    mouseG.append("path") // this is the black vertical line to follow mouse 
     .attr("class", "mouse-line") 
     .style("stroke", "black") 
     .style("stroke-width", "1px") 
     .style("opacity", "0"); 

    var lines = document.getElementsByClassName('line'); 

    var mousePerLine = mouseG.selectAll('.mouse-per-line') 
     .data(cities) 
     .enter() 
     .append("g") 
     .attr("class", "mouse-per-line"); 

    mousePerLine.append("circle") 
     .attr("r", 7) 
     .style("stroke", function(d) { 
     return color(d.name); 
     }) 
     .style("fill", "none") 
     .style("stroke-width", "1px") 
     .style("opacity", "0"); 

    mousePerLine.append("text") 
     .attr("transform", "translate(10,3)"); 

    mouseG.append('svg:rect') // append a rect to catch mouse movements on canvas 
     .attr('width', width) // can't catch mouse events on a g element 
     .attr('height', height) 
     .attr('fill', 'none') 
     .attr('pointer-events', 'all') 
     .on('mouseout', function() { // on mouse out hide line, circles and text 
     d3.select(".mouse-line") 
      .style("opacity", "0"); 
     d3.selectAll(".mouse-per-line circle") 
      .style("opacity", "0"); 
     d3.selectAll(".mouse-per-line text") 
      .style("opacity", "0"); 
     }) 
     .on('mouseover', function() { // on mouse in show line, circles and text 
     d3.select(".mouse-line") 
      .style("opacity", "1"); 
     d3.selectAll(".mouse-per-line circle") 
      .style("opacity", "1"); 
     d3.selectAll(".mouse-per-line text") 
      .style("opacity", "1"); 
     }) 
     .on('mousemove', function() { // mouse moving over canvas 
     var mouse = d3.mouse(this); 
     d3.select(".mouse-line") 
      .attr("d", function() { 
      var d = "M" + mouse[0] + "," + height; 
      d += " " + mouse[0] + "," + 0; 
      return d; 
      }); 

     d3.selectAll(".mouse-per-line") 
      .attr("transform", function(d, i) { 
      //console.log(width/mouse[0]) 
      var xDate = x.invert(mouse[0]), 
       bisect = d3.bisector(function(d) { return d.year; }).right; 
       idx = bisect(d.values, xDate); 

      var beginning = 0, 
       end = lines[i].getTotalLength(), 
       target = null; 

      while (true){ 
       target = Math.floor((beginning + end)/2); 
       pos = lines[i].getPointAtLength(target); 
       if ((target === end || target === beginning) && pos.x !== mouse[0]) { 
        break; 
       } 
       if (pos.x > mouse[0])  end = target; 
       else if (pos.x < mouse[0]) beginning = target; 
       else break; //position found 
      } 

      d3.select(this).select('text') 
       .text(y.invert(pos.y).toFixed(2)); 

      return "translate(" + mouse[0] + "," + pos.y +")"; 
      }); 
     }); 




}); 

</script> 

europe_emission.csv:

年、UNITEDKINGDOM、イタリア、フランス、スペイン、ドイツ
2012,483423,386666,368845,276636,821717
2011,464036 、413379,364819,280922,810441
2010,504997,424993,391075,280377,829401
2009,487442,414809,381992,293732,785602
2008,536733,463695,400720,333181,851111
2007,554251,475436,407254,363744,848548
2006,561128,483533,416414,356712,873246
2005,561101,488078,425740,365478,861733
2004,563962,489367,422201,350071 、881743
2003,562296,486559,420492,333168,893599
2002,551553,470530,412019,328878,890875
2001,567904,468283,416267,308786,907541
2000,556667,462277,415079 、308026,891515
1999,548047,458824,418193,294901,887890
1998,555499,453524,426564,271515,915176
1997,550525,442371,404884,263303,923080
1996,575026,438303,411302,250543,951863
1995,553701,444943,398480,262860,930857
1994,562061,419903,391681,249451 、932485
1993,568100,427170,391484,237253,948683
1992,581828,433867,413020,245814,957561
1991,598323,434156,423121,237179,1004735
1990,591499,434656,398769 、227508,1042065

+0

あなたはこれを見ましたか[回答](http://stackoverflow.com/a/34887578/16363)? – Mark

+0

私はコードと.csvファイルを変更しましたが、それでも問題があります。理由を理解できません...あなたの答えは同じです!...ありがとうございました –

答えて

1

これは私を理解するには時間がかかりすぎましたが、データのソートです。私のリンクは上向きのx軸の値を前提としていたので、下降しているので、あなたのパスはとなり、右から左へとなります。あなたのデータをソート、または右から左に移動するには、検索機能を変更する次のいずれか

 d3.selectAll(".mouse-per-line") 
     .attr("transform", function(d, i) { 

      var beginning = 0, 
      end = lines[i].getTotalLength(), 
      target = null; 

      while (true) { 
      target = Math.floor((beginning + end)/2); 
      pos = lines[i].getPointAtLength(target); 
      if ((target === end || target === beginning) && pos.x !== mouse[0]) { 
       break; 
      } 
      if (pos.x > mouse[0]) beginning = target; //<-- this was end = target 
      else if (pos.x < mouse[0]) end = target; //<-- this was beginning = target 
      else break; 
      } 

      d3.select(this).select('text') 
      .text(y.invert(pos.y).toFixed(2)); 

      return "translate(" + mouse[0] + "," + pos.y + ")"; 
     }); 

固定コードhere

+0

ありがとう!それは完全に動作します! –

関連する問題