Original

Setting up and configuring the Axes

Change the text size

The default size is 10px with the font type of sans-serif.

There are a couple of different ways that we could change the font size and either one is valid.

The first way is to specify the font as a style when drawing an individual axis.

1
2
3
4
svg.append('g')
.style('font', '14px times')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(xScale))

There are a few things to notice here.

Firstly, we do indeed have a larger font and it appears to be of the type ‘times’.

Secondly, the y axis has remained as 10px sans-serif.

Lastly, the number of values represented on the x axis has meant that with the increase in font size there is some overlapping going on

By this way, you can change stype of x axis while leaving y axis away.

But if you want to change two axis meanwhile, you’d better use class.

Change the number of ticks on an axis

Now we shall address the other problem taht cropped up when we change the size of the text. We have overlapping values on the x axis.

The axis component includes a function to specify the number of ticks on an axis.

1
2
3
4
svg.append('g')
.attr('class', 'axis')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(xScale).ticks(5))

Here you may face a confusion:

When you specify ticks to 5 or 4, or 3, there’re always 5 ticks, and if you specify ticks to 2, the axis ticks will be 2 representing month.

This is because D3 is making a command decision for you as to how your ticks should be best displayed.

The following is the list of time interval that D3 will consider when setting automatic ticks on a time based aaxis:

  • 1, 5, 15 and 30-second

  • 1, 5, 15 and 30-minute

  • 1, 3, 6 and 12-hour

  • 1 and 2-day

  • 1-week

  • 1 and 3-month

  • 1-year

You can specify custom time interval by d3.axisBottom(xScale).ticks(d3.timeDay.every(4)).

Rotating text labels for a graph size

An answer to the problem of overlapping axis values might to be rotate the text to provide more space.

1
2
3
4
5
6
7
8
9
svg.append('g')
.attr('class', 'axis')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(xScale).ticks(10))
.selectAll('text')
.style('text-anchor', 'end')
.attr('dx', '-0.8em') // move the end of the text away from the line
.attr('dy', '0.15em') // move the end of the text away from the line
.attr('transform', 'rotate(-65)')

Formatting a date / time axis with specified values

1
2
3
4
5
6
7
8
9
svg.append('g')
.attr('class', 'axis')
.attr('transform', `translate(0, ${height})`)
.call(d3.axisBottom(xScale).tickFormat(d3.timeFormat('%Y-%m-%d')))
.selectAll('text')
.style('text-anchor', 'end')
.attr('dx', '-0.8em')
.attr('dy', '0.15em')
.attr('transform', 'rotate(-65)')

Adding Axis Labels

1
2
3
4
5
6
// text label for the x axis

svg.append('text')
.attr('transform', `translate(${width/2}, ${height + margin.top + 20})`)
.style('text-anchor', 'middle')
.text('Date')

Add y axis

1
2
3
4
5
6
7
svg.append('text')
.attr('transform', 'rotate(-90)')
.attr('y', 0 - margin.left)
.attr('x', 0 - height / 2)
.attr('dy', '1em')
.style('text-anchor', 'middle')
.text('Value')

Something may confused you:

And add the title…

Smoothing out graph lines

1
.curve(d3.curveBasis)

d3.curveLinear

d3.curveLinearClosed

d3.curveStep

d3.curveStepBefore

d3.curveStepAfter

d3.curveBasis

d3.curveBasisOpen

d3.curveLinearClosed

d3.curveBundle

d3.curveCardinal

d3.curveCardinalOpen

d3.curveCardinalClosed

d3.curveMonotone

d3.curveCatmullRom

d3.curveCatmullRomClosed

d3.curveCatmullRomOpen

Make a dashed line

1
2
3
4
5
svg.append('path')
.datum(data)
.attr('class', 'line')
.style('stroke-dasharry', ('3, 3'))
.attr('d', line)

Obviously stroke-dasharray is a style is a style for the path element, but the magic is the numbers.

Essentially they describe the on length and off length of the line. So '(3, 3)' translates to 3px on and 3px off.

You can try '5, 5, 5, 5, 5, 5, 10, 5, 10, 5, 10, 5'

Of course you can apply this style on axis or any where you prefer.

Filling an aera under the graph

Filling an area with a solid color isn’t too hard.

CSS for an area fill
1
2
3
.area {
fill: lightsteelblue
}
Define the area function
1
2
3
4
const area = d3.area()
.x((d) => (xScale(d.date)))
.y0(height)
.y1((d) => (yScale(d.close)))

Draw the area
1
2
3
4
svg.append('path')
.datum(data)
.attr('class', 'area')
.attr('d', area)

If you want to fill the area above the graph

1
2
3
4
const area = d3.area()
.x(d => (xScale(d.date)))
.y0(d => (yScale(d.close)))
y1(0)

Add a drop shadow to allow text to stand out on graphics

1
2
3
4
5
text.shadow {
stroke: white;
stroke-width: 4px;
opacity: 0.8;
}

Add grid lines to a graph.

We are going to use the axis function to generate two more axis elements(one for x and one for y) but for these ones of drawing the main lines and the labels, we’re just going to draw the tick lines.

CSS
1
2
3
4
5
6
7
8
.grid line {
stroke: lightgrey;
stroke-opacity: 0.7;
shape-rendering: crispEdges;
}
.grid path {
stroke-width: 0;
}

Here we use shape-rendering: crispEdges to make the lines narrow.

And set .grid path{ stroke-width: 0; } to dismiss line of top and right line, it will be like this if we remove the css style:

Define the grid line functions
1
2
3
4
5
6
7
8
9
// gridlines in x axis function
function make_x_gridlines() {
return d3.axisBottom(xScale).ticks(5)
}

// gridlines in y axis function
function make_y_gridlines() {
return d3.axisLeft(yScale).ticks(5)
}
Draw the lines
1
2
3
4
5
6
7
8
9
10
// add the x gridlines
svg.append('g')
.attr('class', 'grid')
.attr('transform', `translate(0, ${height})`)
.call(make_x_gridlines().tickSize(-height).tickFormat(''))

// add the y gridlines
svg.append('g')
.attr('class', 'grid')
.call(make_y_gridlines().tickSize(-width).tickFormat(''))
1
axis.tickSize([size])

In our example, we are setting our ticks to a length that corresponding to the full height or width of the graph, which of course means that they extend across the graph and have the appearance of grid lines.

The last thing that is included in the code to draw the grid lines is the instruction to suppress printing any label for the ticks:

1
.tickForamt('')