Data-driven vertical/horizontal lines in d3

mfitzp picture mfitzp · Sep 16, 2013 · Viewed 7.1k times · Source

I am attempting to draw a series of vertical lines on a d3 chart. The data source for this is a list of x positions (in the data) which is mapped through the x() scale function to give the correct position.

At present this is implemented as a for loop for each entry in the labels variable. The y origin and endpoint are taken from the data minY and maxY. A text label is attached to the end of the line.

labels = [
 {
  'x':50,
  'label':test'
 }

 var label = svg.append("g")
        .attr("class","ilabel")

// Labels         
for (var i = 0; i < labels.length; i++) {
    labl = labels[i];

    label.append('line')
        .attr('x1', x( labl.x ) )
        .attr('y1', y( maxY ) )
        .attr('x2', x( labl.x ) 
        .attr('y2', y( minY ) )
        .attr("class","ilabel-line");

    label.append("text")
        .attr("transform", "translate(" +  x( labl.x )+"," + y( maxY )+ ") rotate(-60)")
            .style("text-anchor", "start")
            .attr("dx", ".5em")              
            .attr("class","ilabel-label")

      .text(labl.label);

}

How would I re-write this in a data-driven way i.e. passing the labels in as a .data then iterating over this to draw a series of parallel vertical lines.

var label = svg.selectAll(".ilabel")
      .data(labels)
    .enter().append("g")
      .attr("class","ilabel")

The bit I'm having trouble getting my head around is the x() and y() functions. x() should of course return the x position of the line (which is constant for a given line), but how/what should the y function return to draw a line between two defined points (minY & maxY).

line = d3.svg.line()
  .x(function(d) { return x(d.x); })
  .y(function(d) { return y(d.y); });

label.append('path')
  .attr("d", line)

I feel like I'm missing something obvious.

Answer

user1614080 picture user1614080 · Sep 16, 2013

You could just use the axis functions in d3. Have a look at this example on Bl.ocks you can easily set the ticks using tickValues and then the length of the ticks using innerTickSize and outerTicksize. You'll also need to set the orientation.