2016-06-19 18 views
1

Ich versuche ein interaktives Liniendiagramm mit d3.js zu erstellen. Ich bekomme die Daten von zwei CSV-Dateien (emissions.csv und gdp.csv) und ich möchte, dass, wenn ich mit der Maus auf dem Graphen passiere, es eine Art Etikett mit Informationen über den entsprechenden Punkt auf der Linie zeigt. Jetzt muss ich die Maus über die Linie fahren, um das Etikett zu zeigen und ich kann nicht herausfinden, wie ich das machen soll, was ich tun möchte. Ich habe this Beispiel gefunden, das zeigt, was ich will, aber ich kann einige der Code-Linien nicht verstehen und ich kann nicht verstehen, wie man es auf meinem Diagramm benutzt.
Hier mein Code:Interaktives Liniendiagramm mit 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:

Jahre, United, Italien, Frankreich, Spanien, Deutschland
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
1998555499,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

Haben Sie diese [Antwort] (http://stackoverflow.com/a/34887578/16363) gesehen? – Mark

+0

Ich habe den Code und die .csv-Datei geändert, aber es hat immer noch ein Problem und ich kann nicht verstehen, warum ... es sieht genauso aus wie Ihre Antwort! .. Danke, dass Sie mir geholfen haben –

Antwort

1

Das nahm mir viel zu lange, um herauszufinden, aber es ist Ihre Datensortierung. Meine Verbindung oben nahm eine aufsteigende X-Achse an, die Sie absteigend haben, so dass Ihre Pfade rückwärts von rechts nach links zeichnen. Entweder sortieren Sie Ihre Daten oder die Suchfunktion ändern rechts nach links zu gehen:

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

Fest Code here.

+0

danke! es funktioniert perfekt! –