Data-driven vertical/horizontal lines in d3

回眸只為那壹抹淺笑 提交于 2019-12-24 15:09:06

问题


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.


回答1:


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.




回答2:


I ended up using rect regions instead as shaded areas in preference to lines. However, returning to this I realised that the code is almost the same for drawing a series of rectangles vs. a series of straight lines. The confusion was arising from the d3 function .line() which is used to generate a path. However you can create a series of straight lines by using svg:line and passing data via a generator function (here wrapped in a dictionary):

var line = {
    'x1':(function(d) { return x( labl.x ); }),
    'y1':(function(d) { return y( maxY ); }),
    'x2':(function(d) { return x( labl.x ); }),
    'y2':(function(d) { return y( minY) }),
    }


var label = svg.selectAll(".labels")
      .data(labels)
      .enter();

    label.append("svg:line")
            .attr("x1", line.x1)
            .attr("y1", line.y1)
            .attr("x2", line.x2)
            .attr("y2", line.y2)
        .attr("class","label-line");


来源:https://stackoverflow.com/questions/18825721/data-driven-vertical-horizontal-lines-in-d3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!