I have this code which outputs a straight line composed of a bunch of line segments:
var width = 400;
var height = 100;
var data = [1,1,1,1,1,1,1,1,1,1];
var lineSegments = data.length + 1;
d3.select("body").append("svg")
.attr({
width: width,
height: height
})
.selectAll("line")
.data(data)
.enter()
.append("line")
.attr({
x1: function (d, i) { return i * (width / lineSegments); },
x2: function (d, i) { return (i + 1) * (width / lineSegments); },
y1: function (d, i) { return height / 2; },
y2: function (d, i) { return height / 2; },
stroke: "black",
"stroke-width": 2
});
I want every 3d segment to be offset in the y direction by, say 10px, and I need the offset to be cumlative, i.e. the 3d element should have offset 10px, the 6th element should be offset 20px, etc.
This should result in a line like this:
How should I modify the code to get it to work? Is there a special d3 way of doing this?
You can use d3's selection.each()
to target every 3d segment. This method has some useful variables for performing various functions.
line.each(function(d, i) {
console.log(i); // prints the current index
console.log(d); // prints the data at the current index
console.log(this); // prints the current DOM element
}
In your specific case, the i
variable is useful to you. You can use this inside of an if
statement to change the attributes of every 3rd element. Your revised code might be...
var width = 400;
var height = 100;
var data = [1,1,1,1,1,1,1,1,1,1];
var lineSegments = data.length + 1;
var offset = 5;
d3.select("body").append("svg")
.attr({
width: width,
height: height
})
.selectAll("line")
.data(data)
.enter()
.append("line")
.attr({
x1: function (d, i) { return i * (width / lineSegments); },
x2: function (d, i) { return (i + 1) * (width / lineSegments); },
y1: function (d, i) { return height / 2; },
y2: function (d, i) { return height / 2; },
stroke: "black",
"stroke-width": 2
})
.each(function(d,i) {
if (i !== 0 && i % 3 === 0) {
d3.select(this).attr('transform', 'translate(0,' + offset + ')');
offset += 5;
}
})