Okay, I\'m starting to get a little more familiar with D3 but am still a little hazy on some things. I\'m now trying to draw grid lines but am realizing that I may be hackin
Following @arete's idea, you can use the following to avoid re-drawing unnecessarily the gridline:
function createsGrid(data) {
var grid = gridLine.selectAll("line.horizontalGrid").data(scaleY.ticks());
grid.enter()
.append("line")
.attr("class","horizontalGrid");
grid.exit().remove();
grid.attr({
"x1":0,
"x2": width,
"y1": function (d) { return scaleY(d); },
"y2": function (d) { return scaleY(d); }
});
}
and define the following in your CSS file
line.horizonalGrid{
fill : none;
shape-rendering : crispEdges;
stroke : black;
stroke-width : 1.5px;
}
Assuming that you have Mike Bostock's standard margins defined and you have defined a linear scale for the y-axis the following code will create horizontal gridlines without using tickSize()
.
svg.selectAll("line.horizontalGrid").data(yScale.ticks(4)).enter()
.append("line")
.attr(
{
"class":"horizontalGrid",
"x1" : margin.right,
"x2" : width,
"y1" : function(d){ return yScale(d);},
"y2" : function(d){ return yScale(d);},
"fill" : "none",
"shape-rendering" : "crispEdges",
"stroke" : "black",
"stroke-width" : "1px"
});
I would suggest to use d3.svg.axis().scale() to tie up the grid to your coordinates. I drew a quick example based on your code: http://jsfiddle.net/temirov/Rt65L/1/
The gist is to use the existing scales, x and y, and to use ticks as grid. Since yAxis and xAxis are already defined we can just re-use them. Here is the relevant code:
//Draw a grid
var numberOfTicks = 6;
var yAxisGrid = yAxis.ticks(numberOfTicks)
.tickSize(w, 0)
.tickFormat("")
.orient("right");
var xAxisGrid = xAxis.ticks(numberOfTicks)
.tickSize(-h, 0)
.tickFormat("")
.orient("top");
svg.append("g")
.classed('y', true)
.classed('grid', true)
.call(yAxisGrid);
svg.append("g")
.classed('x', true)
.classed('grid', true)
.call(xAxisGrid);
In the d3fc project we have created a gridlines component that renders in exactly the same way as the D3(v4) axis.
Here's an example of the usage:
var width = 500, height = 250;
var container = d3.select("#gridlines")
.append("svg")
.attr("width", width)
.attr("height", height);
var xScale = d3.scaleLinear()
.range([0, 100]);
var yScale = d3.scaleLinear()
.range([0, 100]);
var gridline = fc.annotationSvgGridline()
.xScale(xScale)
.yScale(yScale);
container.append("g")
.call(gridline);
Which renders as follows:
The spacing of the gridlines is determined by the ticks supplied by the associated axes.
Disclosure: I am a core contributor to the d3fc project!
You could just use innerTickSize, instead of tickSize:
var xAxis = d3.svg.axis()
.scale(xScale)
.orient("bottom")
.ticks(1)
.innerTickSize(-h);
You could use the ticks()
function of your scale to get the tick values and then use them in a data call to draw the lines.
var ticks = xScale.ticks(4);
rules.selectAll("path.xgrid").data(ticks).enter()
.append("path")
.attr("d", function(d) {
return "M" + xScale(d) + " " + padding + "L" + xScale(d) + " " + (h-padding);
});
You may prefer using a line generator for the grid lines instead of creating the path manually. This works similarly for y grid lines, only that the y coordinate is constant and ranges from 0 to width of graph. You may need to adjust the start and end values to make it look "nice".