问题
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