Axis labels not showing in d3 chart - javascript

I am new to D3 and currently trying to create a line graph. The axis are created with the right dimensions, however the label for the axes are not showing up. They are there, as when I highlight where they are supposed to be, they show up. They must be hidden or being displaying with a white fill but I'm not sure as to why that is happening. Below is my code for adding axes to the chart.
var xScale = d3.scaleTime()
.domain(d3.extent(data[0].values, d => d.date))
.range([0, width1-margin1]);
var yScale = d3.scaleLinear()
.domain([0, 40])
.range([height1-margin1, 0]);
/* Add Axis into SVG */
var xAxis = d3.axisBottom(xScale).ticks(10);
var yAxis = d3.axisLeft(yScale).ticks(10);
svg1.append("g")
.attr("class", "x axis")
.attr("transform", `translate(0, ${height1-margin1})`)
.call(xAxis);
svg1.append("g")
.attr("class", "y axis")
.call(yAxis)
}
The values are there, they are just not displayed for some reason

Related

In D3 v4, how do I align axes appropriately?

I am using D3 v4. I have a bar graph created with an x-axis using scaleBand(). Now, I have created a y-axis but my issue is that no matter how I position it, it is cutting into the actual bars of the graph.
At the top of my JS file, I have:
var width = 350;
var height = 300;
Then, the part where I actually create the Y-axis:
var y = d3.scaleLinear()
.domain([0, 300000])
.rangeRound([height, 0]);
var yAxis = d3.axisRight(y);
yAxis.ticks(6);
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (width - dist_from_right) + ", 0)")
.call(yAxis);
As you can see from the picture, the axis stretches the entirety of the height of the SVG, from bottom to top meaning that half of the 0 gets cut off and half off the 300,000 gets cut off.
First question: how do I "squish" (or scale) the y-axis so that it displays within the confines of the SVG?
Next, I want to translate the y-axis so that it is not cutting into my red bar. If I try to use the transform attribute, I can push the axis far to the right of the SVG borders but that means the numbers are off the SVG boundary. I've also tried to increase the width variable but that does nothing because it just stretches out the x-axis proportionally.
Second question: how do I move the y-axis so that it is not cutting into the x-axis and red bar and also remains visible in the SVG window?
Thanks!
In D3, axes are positioned according to the range of corresponding scales. So, you need a "padding" for the ranges. Right now, as your range goes from 0 to height (or vice versa, it doesn't matter), the axis starts at the very beginning of the SVG and ends at its very end.
I see you have a dist_from_right, but I don't know what are you doing with it in your x scale. So, for now, let's suppose you don't have any padding.
First, let's set the paddings:
var paddingLeft = 10, paddingRight = 10, paddingTop = 10, paddingBottom = 10;
Here, 10 is just a given number, change it accordingly.
After that, set the ranges using the paddings:
var y = d3.scaleLinear()
.domain([0, 300000])
.rangeRound([height - paddingBottom, paddingTop]);
The same for your x scale:
var x = d3.scaleLinear()
.domain([0, someValue])
.rangeRound([paddingLeft, width - paddingRight]);
Then you define the axis:
var xAxis = d3.axisBottom(x);//the same for the y axis
Having the ranges with the paddings, call the axes setting that paddings:
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (width - paddingRight) + ", 0)")
.call(yAxis);
And the same for the x axis:
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height - paddingBottom) + ")")
.call(xAxis);
Here is a working example. I made the SVG light gray and the plotting area white, so you can see the paddings.:
var paddingLeft = 20, paddingRight = 40, paddingTop = 10, paddingBottom = 40;
var width = 300, height = 300;
var chart = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
chart.append("rect")
.attr("x", paddingLeft)
.attr("y", paddingTop)
.attr("width", width - paddingLeft - paddingRight)
.attr("height", height - paddingTop - paddingBottom)
.attr("fill", "white");
var y = d3.scaleLinear()
.domain([0, 100])
.rangeRound([height - paddingBottom, paddingTop]);
var x = d3.scaleLinear()
.domain([0, 100])
.rangeRound([paddingLeft, width - paddingRight]);
var yAxis = d3.axisRight(y);
var xAxis = d3.axisBottom(x);
chart.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + (width - paddingRight) + ", 0)")
.call(yAxis);
chart.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + (height - paddingBottom) + ")")
.call(xAxis);
svg {
background-color: lightgray;
}
<script src="https://d3js.org/d3.v4.min.js"></script>

How to have the same scale in both x and y

I have this graph : http://jsfiddle.net/thatOneGuy/Rt65L/94/
I can't seem to figure out how to get the same scale in both x and y. What I need is the same distance between the ticks on both but I need the x axis to be 600px long and y axis to be 300px high.
I have tried calling the same scale but obviously the x scale is too big for the y. Any ideas ?
<svg id='svgContainer' width="1000" height="700"> </svg>
var container = d3.select('#svgContainer')
.style('stroke', 'red')
var width = 600, height = 300;
var xScale = d3.scale.linear()
.range([0, width]);
var yScale = d3.scale.linear()
.range([0, height]);
var xTicks = width/50;
var yTicks = height/50;
var xAxis = d3.svg.axis()
.scale(xScale)
.innerTickSize(-(height)) // vertical grid lines
.outerTickSize(0)
.orient("bottom")
.ticks(xTicks);
var yAxis = d3.svg.axis()
.scale(yScale)
.innerTickSize(-(width)) // horizontal grid lines
.outerTickSize(0)
.orient("left")
.ticks(yTicks);
container.append("g")
.attr("class", "x axis")
.attr("transform", "translate(50," + (height+20) + ")")
.call(xAxis)
container.append("g")
.attr("class", "y axis")
.attr("transform", "translate(50,20)")
.call(yAxis)
If you don't set the domain, D3 will automatically set it as [0, 1]. So, I believe that, in your case, it's simply a matter of setting the domains:
var xScale = d3.scale.linear()
.range([0, width])
.domain([0,1]);
var yScale = d3.scale.linear()
.range([height, 0])
.domain([0,0.5]);
Here is the fiddle: http://jsfiddle.net/gerardofurtado/Rt65L/96/

Tick marks on both sides of axis on d3 scale

I'm trying to have the tick marks show up on both sides of the y axis. As the code is shown below, I'm able to extend the tick marks based on length -width which draws the tick mark from a starting point from left to right.
Is it possible to move the starting point of the tick mark further to the left?
My intent is aesthetics, but to have the tick values be directly over a length of the tick marks.
I have a grid set up, made up of container-length tick marks:
// Axis
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickSize(-height);
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
.tickSize(-width)
.tickFormat(d3.format("s"));
Based on these scales:
// Scale
var x = d3.time.scale()
.range([0, width]);
var y = d3.scale.linear()
.range([height, 0]);
My axis are appended to the svg like this:
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.call(adjustXLabels);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.call(adjustYLabels);
I'm a little confused about what you're after. Do you want the tick labels to overlap with the ticks themselves? If so you can select the text after the axis is drawn and then translate the ticks.
See the fiddle here: https://jsfiddle.net/6q3rpw6j/
The key bit is:
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.selectAll(".tick text")
.attr("transform", "translate(15,0)");
EDIT
To move the ticks themselves:
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.selectAll(".tick line")
.attr("transform", "translate(15,0)");
And to remove the top and bottom end ticks, make sure you set the .outerTickSize(0)

d3.js - update axis and change width of path

I'm trying to update the width of my axis like so:
Initial setup with zero width:
var x2 = d3.scale.linear()
.domain([0, 10])
.range([0, 0])
.clamp(true);
svg.append("g")
.attr("class", "x axis2")
.attr("transform", "translate(0," + height / 2 + ")")
.call(d3.svg.axis()
.scale(x2)
.orient("bottom")
.tickFormat(function(d) { return d; })
.tickSize(0)
.tickPadding(12))
.select(".domain")
.select(function() { return this.parentNode.appendChild(this.cloneNode(true)); })
.attr("class", "bar-highlight");
Later I want to update the width of the path (with a nice transition would be great). I tried it like suggested in this answer, with no luck:
x2 = d3.scale.linear()
.domain([0, data.page_count])
.range([0, 15])
.clamp(true);
d3.selectAll("g.x.axis2")
.call(x2);
You need to call d3.svg.axis().scale(x2) on the axis, not just x2. The following update procedure works for me (albeit on an empty plot):
// Update the range of existing variable, x2
x2.range([0, 15]);
// Select and change the axis in D3
d3.selectAll("g.x.axis2")
.call(d3.svg.axis().scale(x2));

Unable to align ticks with d3.js

Working with one bar chart with d3.js I am unable to align ticks in x axis with bars.
In left and right verges the ticks are ok, but not in the middle.
Here is the code:
var formatDate = d3.time.format("%e %b");
var height = 325;
var xTimeScale = d3.time.scale()
.domain([new Date(data[0].date), d3.time.day.offset(new Date(data[data.length - 2].date), 1)])
.range([30, width]);
var xAxis = d3.svg.axis()
.scale(xTimeScale)
.orient("bottom")
.ticks(d3.time.days, .1)
.tickFormat(formatDate);
chart.append("g")
.attr("class", "xaxis axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
chart.selectAll(".xaxis text")
.attr("transform", function(d) {return "translate(" + this.getBBox().height * -2 + "," + this.getBBox().height + ")rotate(-45)";});
What am I missing?
Thanks in advance.
Update: Here is the jsFiddle updated with chrtan suggestions.
My problem now is to align text with the center of bar and not in left.
From the looks of your graph, you lost a bar's worth of space. If all the bars are supposed to be left-aligned against a tick, that final bar you have should be to the right of the January 31st tick.
You might need to add the February 1st tick by perhaps changing the [data.length - 2] to [data.length - 1] in the domain() for your xTimeScale.
Then for display purposes, you could probably remove the last tick axis text with:
d3.select(chart.selectAll(".xaxis text")[0].pop()).remove();
The inner selectAll should get the array containing your xAxis tick texts and then pop the very last tick. This last tick should then be removed by the outer select.
An example with an auto time ticks with d3.js
// set domain for axis
var x_domain = d3.extent(data, function(d) { return new Date(d.date); });
//format date
var date_format = d3.time.format('%Y %B');
var vis = d3.select("#graph")
.append("svg:svg")
.attr('class', 'chart')
.attr("width", width)
.attr("height", height);
var yScale = d3.scale.linear()
.domain([0, d3.max(data, function(d) { return d.data; })]).nice()
.range([height - padding, padding]);
var xScale = d3.time.scale()
.domain(x_domain)
.range([padding, width - padding]);
// define the y axis
var yAxis = d3.svg.axis()
.orient("left")
.scale(yScale);
// define the x axis
var xAxis = d3.svg.axis()
.orient("bottom")
.scale(xScale)
.tickFormat(date_format);
// draw y axis with labels and move in from the size by the amount of padding
vis.append("g")
.attr("class", "axis")
.attr("transform", "translate("+padding+",0)")
.call(yAxis);
// draw x axis with labels and move to the bottom of the chart area
vis.append("g")
.attr("class", "xaxis axis")
.attr("transform", "translate(0," + (height - padding) + ")")
.call(xAxis);
// and set data in graph...
a great example : http://bl.ocks.org/phoebebright/3061203

Categories

Resources