Skip to content Skip to sidebar Skip to footer

D3.js Multi-series Chart With Y Value Tracking

Working solution: Right now I'm working on styling and on solving some of the issues regarding my problem with creating chart consisting of multiple-data series with values trackin

Solution 1:

You've got all the basic code there, you just need to get it all to run at the same time.

The first problem is that you're setting two different "mousemove" event handlers on the same elements. Unless you use namespaces to distinguish them, the second function just replaces the first, so your first function is never getting called. Rather than creating two event handlers with different namespaces, it's much easier to just put all your event-handling code into one function.

The second problem is that you only have one "focus" element, and so even if you did run both functions to set the two different tooltip contents and position, only the second version would be displayed, because it just replaces the first.

So to recap, you need to: create a tooltip/focus element for each path, and then have one event-handling function that sets all the values and positions according to the appropriate column of your data file.

To keep the code concise, and to allow you to quickly switch from two lines to four or more, I'm going to suggest that you create the focus elements as a data-joined selection, where the data is an array of column names:

var columnNames = d3.keys( data[0] ) //grab the key values from your first data row//these are the same as your column names
                  .slice(1); //remove the first column name (`date`);var focus = svg.selectAll("g")
    .data(columnNames)
  .enter().append("g") //create one <g> for each columnName
    .attr("class", "focus")
    .style("display", "none");

focus.append("circle") //add a circle to each
    .attr("r", 4.5);

focus.append("text")  //add a text field to each
    .attr("x", 9)
    .attr("dy", ".35em");

Now, when you show or hide focus in the mouseover/mouseout events, it will show or hide all the tooltips:

svg.append("rect")
  .attr("class", "overlay")
  .attr("width", width)
  .attr("height", height)
  .on("mouseover", function() { focus.style("display", null); })
  .on("mouseout", function() { focus.style("display", "none"); })
  .on("mousemove", mousemove);

But what should you do in your mousemove function? The first part, figuring out the nearest x-value (date) is the same. But then you have to set the text and position of each focus tooltip according to the values in the correct column. You can do this because each focus element has a column name bound to it as a data object, and d3 will pass that data object as the first parameter to any function you pass in to a d3 method:

functionmousemove() {
  var x0 = x.invert(d3.mouse(this)[0]),
    i = bisectDate(data, x0, 1),
    d0 = data[i - 1],
    d1 = data[i],
    d = x0 - d0.date > d1.date - x0 ? d1 : d0; 
       //d is now the data row for the date closest to the mouse position

   focus.attr("transform", function(columnName){
         return"translate(" + x( d.date ) + "," + y( d[ columnName ] ) + ")";
   });
   focus.select("text").text(function(columnName){
         //because you didn't explictly set any data on the <text>//elements, each one inherits the data from the focus <g>returnformatCurrency(d[ columnName ]);
   });
}

By the way, you can use this same structure -- use the column names as data, and then use that name in a function to grab the correct data value -- to create all your lines with the same code, without having to create separate data arrays. Let me know if you have difficulty implementing that.

Post a Comment for "D3.js Multi-series Chart With Y Value Tracking"