简体   繁体   中英

Tooltips for multiple line graphs in D3

I am new to D3 and my requirement is to get multiple line graphs and provide tooltips for them.

I could get the multiple line graphs to appear but i am going wrong in getting multiple tooltip points.

I am new to javascript as well. So any help will be much appreciated.

Here is my code.

<script>

 function showData(obj, d) {
 var coord = d3.mouse(obj);
 var infobox = d3.select(".infobox");
 // now we just position the infobox roughly where our mouse is
 infobox.style("left", (coord[0] + 200) + "px" );
 infobox.style("top", (coord[1] - 130) + "px");
 $(".infobox").html(d);
 $(".infobox").show();
 }

 function hideData() {
 $(".infobox").hide();
 }

    var xx,yy;
    function xx(e) { 
    return x(e.date); };
    function yy(e) { 
    return y(e.returns); };

 var draw = function()  {   

        var margin = {top:100,left:200,right:200,bottom:100},
        width = 1150 - margin.left - margin.right,
        height = 500 - margin.top - margin.bottom;


        var parseDate = d3.time.format("%Y-%m-%d").parse;

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

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

        //values of the axis is plotted here
        var xAxis = d3.svg.axis().scale(x).orient("bottom");

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

        var svg = d3.select("#chart").append("svg")
                  .attr("width" , width + margin.left + margin.right)
                  .attr("height" , height + margin.top + margin.bottom)
                  .attr("pointer-events" , "all")
                 .append("g")
                  //this is the line that positions the graph
                 .attr("transform" , "translate(" + margin.left + "," + margin.top +") ");      

        var activeReturns = new Array();
        var passiveReturns = new Array();
        var D3Obj = new Array();

        var line = d3.svg.line()
                .interpolate("basis")
                .x(function(d) { return x(d.date); })
                .y(function(d) { return y(d.returns);});

        d3.json("d3.v3/sample1.json",function(error,result) {
        result.data.forEach(function(d){

            var arObj = new Object();
            arObj.date = parseDate(d.date);
            arObj.returns = +d.returns;

            var prObj = new Object();
            prObj.date = parseDate(d.date);
            prObj.returns = +d.ticker_performance;

            activeReturns.push(arObj);
            passiveReturns.push(prObj);

        });

        D3Obj.push(activeReturns);
        D3Obj.push(passiveReturns);


        // this is where i tell that the line graph to be done


    x.domain(d3.extent(D3Obj[0], function(d) {return d.date ;} ));
    y.domain(d3.extent(D3Obj[0], function(d) {return d.returns ;} ));

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


    svg.append("g")
        .attr("class" , "y axis")
        //this is where yaxis line is added
        .call(yAxis)
    .append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("dy", ".71em")
        .style("text-anchor", "end")
        .text("Price ($)");

   svg.selectAll(".line")
   .data(D3Obj)
   .enter().append("path")
   .attr("class","line")
   .attr("d",line)

//this is where i am adding the tooltips
 //tooltip for 1st line
svg.selectAll("circle")
 .data(D3Obj[0])
 .enter().append("circle")
 .attr("fill", "red")
 .attr("r", 2)
  .attr("cx", xx)
 .attr("cy", yy)
 .on("mouseover", function(d) { showData(this, d.returns);})
 .on("mouseout", function(){ hideData();});

 //tooltip for 2nd line - this is where i think i am going wrong.
 svg.selectAll("circle")
 .data(D3Obj[1])
 .enter().append("circle")
 .attr("fill", "steelblue")
 .attr("r", 2)
  .attr("cx", xx)
 .attr("cy", yy)
 .on("mouseover", function(d) { showData(this, d.returns);})
 .on("mouseout", function(){ hideData();});


});

 $("#chart").append("<div class='infobox' style='display:none;'>Test</div>");

};
</script>

When you are creating the second point, nothing actually happens. The .data() function will try to match the data elements you pass to what you have selected (in this case one circle) and will succeed here. This means that your enter selection is empty and nothing happens.

The d3 way is to pass in all the data you want to use to create elements at once and handle accordingly in the functions to set attributes etc. That is, your code should look something like

svg.selectAll("circle")
   .data(D3Obj)
   .enter().append("circle")
   .attr("fill", function(d, i) { if(i == 0) { return "red"; } else { return "steelblue"; } })
   .attr("r", 2)
   .attr("cx", xx)
   .attr("cy", yy)
   .on("mouseover", function(d) { showData(this, d.returns);})
   .on("mouseout", function(){ hideData();});

This will create two circles and attach the corresponding listeners to them.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM