I am available for work right now, if you are interested then email me directly.
Up until now when I have been dealing with d3.js’s axes components, I have always kept the axes positive, i.e. both the x and y axes where showing values greater than 0.
I have been hacking around with this fun side project that takes the input of an algebraic expression and plots a graph for a sample range of values for x. You can checkout the source code here if you are interested.
Below is a screenshot of the end result:
It quickly became apparent that in order to show the curve of the expression properly, I would need to construct negative and positive x and y axes.
I have the following function below that constructs the data of x and y coordinates to plot the curve against which uses the excellent mathjs library to transform the string algebraic expression into a javascript function (line 2). I then create a sample range for x
values ranging from 10
to 11
and evaluate the y
coordinate for each item in the range by applying the function on line 5 to each item:
1 2 3 4 5 6 7 8 9 10 11 12 

Armed with this data, I can now construct my axes.
I first create the axis against a scale that is in proportion with the viewport dimensions.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 

The domain
function of d3
allows you to specify a minimum and maximum value as the range of values that we can use for a particular axis.
Below I am using d3’s extent
function that returns the minum and maximum values of an array and is equivalent to calling d3.min
and d3.max
simultaneously.
1


As I am supplying the values for the range of x
values in the code above, I know that I will always have negative x
values and positive x
values.
The y coordinates are different depending on the function generated from the algebraic expression. Depending on the expression, there are basically 3 conditions I want to capture when displaying a curve.
The first case is when there are only positive y values:
The next case is when there are both negative and positive y values;
Lastly, only negative y values:
With this in mind, the code below creates a domain based on the minimum values of y and the maximum values of y:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 

I either start my domain at 0
or use d3.extent
again to get the maximum and minimum values for y like I did before for x.
The last problem to solve was to position the x axis. In the 3 code samples below, I am capturing the domain for y and the x axis position for each condition.
This is easy if I only have negative or positive values for y
. I can simply place the x
axis at the bottom for only positive values:
1 2 

When I have only negative values, then I can place the x axis at the top of the document:
1 2 

The interesting case was when I have both positive and negative values for y
.
What I ended up doing was selecting all the ticks or labels from the y axis and finding the label that had 0
against it and from that I could use d3 to to select its position and then use that for my x axis position.
Below is the code that does that:
1 2 3 4 5 

In the code above, I filter out all the other ticks apart from the 0
label. The zero tick is then passed into the map
function which selects the transform attribute of the tick which might look something like this translate(0,280)
. The second value of translate, 280
in this instance gives me the position of the 0
label in the y axis. I can use this value to position my x axis.
Once I have the position of 0 in the y axis, I can position the axis to the document:
1 2 3 4 

When it comes to positioning the y axis, I simply divide the width by 2 and position it there:
1 2 3 4 

I am available for work right now, if you are interested then email me directly.