0

I am new to D3.js and currently developing a line chart for one of my projects. I referred the documentation and example here and created my own version here. Now, I am planning to add two interactive features here:

  1. On mouseover in the chart draw a vertical line to the nearest data point.
  2. Show a label with X and Y attributes next to this vertical line.

To make this features more clear, please refer this example.

Here is what I tried which came from a suggestion:

svg.append("g")        // creating new 'group' element
.selectAll('rect')     // adding a rectangle for the label
.selectAll('line');    // adding a line

However, the line ans rectangle doesnt show up. I have been Googling a lot but in no vain. What am I missing?

jsFiddle

Rahul Desai
  • 15,242
  • 19
  • 83
  • 138
  • Have you seen [NVD3](http://nvd3.org/)? – Lars Kotthoff Feb 13 '14 at 10:19
  • @LarsKotthoff: Thank you for the suggestion but I am restricted to use D3 library only. – Rahul Desai Feb 13 '14 at 10:20
  • 1
    with the .selectAll('rect') and .selectAll('line') you are selecting all the rectangles and lines inside the 'g' element you just created, which is empty. That's why you are not getting those elements to show up. – tomtomtom Feb 13 '14 at 13:23
  • [This answer should help you figure out the nearest datapoint based on the mouse position](http://stackoverflow.com/a/21744213/3128209). [This tutorial should help you figure out how to position an HTML tooltip overtop of your SVG](http://codepen.io/AmeliaBR/pen/kFDvH). But you're also going to need to spend some more time with [d3 tutorials](https://github.com/mbostock/d3/wiki/Tutorials) and building your own simple charts in order to clearly understand how selections work (and don't work). – AmeliaBR Feb 13 '14 at 17:14

1 Answers1

2
//create groups for line and label (and invisible selection area)
var infos = svg.append('g')
  .selectAll('rect')
  .data(data)
  .enter()
  .append('g')
//move to datapoint location
  .attr('transform',function(d,i){d.x = x(d.date)  ; d.y = 0; return "translate(" + d.x + "," + d.y + ")";});

//create and select line "rectangles" (easier than doing actual lines)
infos.append("rect")
.attr('class','line')
.attr('height', height)
.attr('width', 1)
.attr('opacity',0);

//create and select line "rectangles" (easier than doing actual lines)
infos.append("rect")
.attr('class','area')
.attr('height', height)
//should probably do something to make sure they don't overlap, such as measure distance between neighbours and use that as width
.attr('width', width/data.length/2)
.attr('opacity',0)
//move so that the data point is in the middle
.attr('x',-width/data.length/4)
.on('mouseover', function(){
    g_elem = this.parentNode;
    d3.select(g_elem).selectAll(".line").attr("opacity",1);
})
.on('mouseout', function(){
    g_elem = this.parentNode;
    d3.select(g_elem).selectAll(".line").attr("opacity",0);
});

http://jsfiddle.net/SKb8W/7/

For labels, here is a useful example: http://jsfiddle.net/WLYUY/5/ (from D3.js: Position tooltips using element position, not mouse position?)

And for using mouse coordinates you can do something like:

var coordinates = [0, 0];
coordinates = d3.mouse(this);
var x = coordinates[0];
var y = coordinates[1];

(from Mouse position in D3)

Community
  • 1
  • 1
Mosho
  • 7,099
  • 3
  • 34
  • 51