D3.js: yAxis text bold and blur - d3.js

I am trying to plot a customized yAxis using D3.js. My ideal result should be like this: JSFiddle.
But I haven't found the way to export the SVG image together with CSS styles. So I would like to move the styles to the SVG elements:
var yNode = svg.append("g")
.style("fill", "none")
.style("stroke", "#000")
.attr("transform", "translate(" + left + ",0)")
.attr("class", "axis")
.call(yAxis);
yNode.selectAll('text')
.style('font-size', '11px')
.style('font-family', 'Lucida Console');
The code is here: JSFiddle.
All the styles are the same. But somehow the yAxis label of the later one becomes blur and bold. How to fix it? Thanks.

Here it is : JsFiddle
You selected the whole axis dom element and applied the fill: none and stroke: black to it. The axis contains both: the path and the text, and both are going to be affected by the stroke. That's why your text is stroked.
So I commented out the fill & stroke here
var yNode = svg.append("g")
//.style("fill", "none")
//.style("stroke", "#000")
.attr("transform", "translate(" + left + ",0)")
//.attr("class", "axis")
.call(yAxis);
Selected the path and added the fill and stroke styles
yNode.select('path')
.style("fill", "none")
.style("stroke", "#000");

Related

make x axis and ticks disappear in d3

I'd like to make only the x-axis labels disappear. Currently, I have the following code, but it makes the entire x-axis disappear, and I'd like to keep the horizontal line.
Is there a way to just target the ticks and the text alone?
// Make x-axis
let xAxis = d3.axisBottom(scaleX);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + height + ")")
.attr("opacity", 0.7)
.call(xAxis);
// Target x-axis; but this targets the entire axis
let setXAxisOpacity = (opacity, duration=120) => {
d3.select(".axis")
.transition()
.duration(duration)
.ease(d3.easeLinear)
.style("opacity", opacity)
}
you need to target the text and line parts of the axis
d3.select('.axis').selectAll('text')
.transition()
.duration(duration)
.ease(d3.easeLinear)
.style("opacity", opacity);
d3.select('.axis').selectAll('line')
.transition()
.duration(duration)
.ease(d3.easeLinear)
.style("opacity", opacity);

d3 bar chart exit not quite working

i have a fiddle of a bar that I am working on. I needed it to update dynamically. the problem I am having is the x axis exit and call for when the bar is re drawn. the title on the x-axis is not removed when an array item is removed.
bars.exit()
.transition()
.duration(1000)
.attr("width", 0)
.remove();
d3.transition(svg).select(".x.axis")
.transition()
.duration(1000)
.call(d3.axisBottom(x));
my bar
Since you are selecting by class, it's a good idea setting the class when drawing the axis:
svg.append("g")
.attr("class", "x axis")//set the class here
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x));
Here is your updated fiddle with that change: https://jsfiddle.net/3mkd3njj/

D3 x axis Formatting

I want to format the x axis text with more padding and space and I am not able to achieve this. The actual text is around 6-7 characters long, but it is only showing 3. Here is the extract of the code and a screenshot:
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("transform", "rotate(90)");
d3 bar chart
When rotating the text in the ticks, you have to set the x and y. Also, it's a good idea changing the text-anchor. Something like this:
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.attr("y", 0)//tweak this value
.attr("x", 10)//tweak this value
.attr("dy", ".35em")//tweak this value
.attr("transform", "rotate(90)")
.style("text-anchor", "start");
Check the demo:
var svg = d3.select("body")
.append("svg")
.attr("width", 400)
.attr("height", 100);
var data = ["foo", "bar", "baz", "foobar", "foobaz"];
var scale = d3.scaleBand()
.range([0, 400])
.domain(data);
var axis = d3.axisBottom(scale);
var gX = svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0,30)")
.call(axis)
.selectAll("text")
.attr("y", 0)//tweak this value
.attr("x", 10)//tweak this value
.attr("dy", ".35em")//tweak this value
.attr("transform", "rotate(90)")
.attr("font-size", 14)
.style("text-anchor", "start");
<script src="https://d3js.org/d3.v4.min.js"></script>

D3 time scales being split onto two lines

I have a time-series d3.js chart which I can't seem to get lined up properly. Initially I create the x-axis with:
var x_domain = d3.extent(active_data, function(d) { return d.date; })
var x = d3.time.scale()
.domain(x_domain)
.range([bar_width/2, width-bar_width/2]); // stop bars going outside chart
var date_format = d3.time.format("%b %y");
var xAxis = d3.svg.axis()
.orient("bottom")
.scale(x)
.ticks(8)
.tickFormat(date_format);
// create the xAxis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)");
svg.selectAll(".x text") // some legacy code I had lying around
.attr("transform", function(d) {
return "translate(" + this.getBBox().height*3 + "," + this.getBBox().height + ")rotate(0)";
and then I update later on when user selects a date range. "active_data" is updated with the actual values/dates that will show from my total data before this update.
function update_chart(start){
/*...update active_data and other stuff...*/
x.domain(d3.extent(active_data, function(d){return d.date;}))
.range([bar_width/2, width-bar_width/2]);
/*...*/
var svg = d3.select("body").transition().duration(500);
svg.select(".x.axis").call(xAxis);
}
There's a lot more going on, but those are the related bits that I'm having trouble with. I've tried everything I can think of, searched online and I just don't understand what I'm doing wrong. It produces the following sort of problem:
d3 time scale some ticks on second line
You can see the dates go onto the second line. On some charts, when I update to the lowest or the maximum date, it draws it correctly, then draws all of them correctly afterwards. On another chart, it does this:
ticks all over each other
On this second one, I don't change the .ticks(8), so I don't know why it does that. Any insight would be greatly appreciated.
Ok I figured it out, and there were a couple bugs.
Then, the following was giving some dates a special x location, but not all of them:
// create the xAxis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", "-.55em")
.attr("transform", "rotate(-90)");
I changed it to:
// create the xAxis
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
and let the update do all the work (let D3 figure it out). The date was now in the right spot, except it was vertical instead of horizontal. I fixed that by removing this:
svg.selectAll(".x text") // some legacy code I had lying around
.attr("transform", function(d) {
return "translate(" + this.getBBox().height*3 + "," + this.getBBox().height + ")rotate(0)";
And it works properly!

Zooming bar-graph with d3.js

I am trying to create a bar graph with a time scale where its possible to zoom into any time period. I was able to create the zooming functionality for my x-axis(time scale) however my data (in this case rects) doesn't zoom along with my axis.
Here is a simplified version of my graph: http://jsfiddle.net/gorkem/Mf457/5/embedded/result/
As you can see I can zoom in to my x-axis but the bars do not zoom along.
and here is the jfiddle link: http://jsfiddle.net/gorkem/Mf457/6/
var y = d3.scale.linear().domain([0, max_val]).range([graph_height, 0]);
var x = d3.time.scale().domain([minDate, maxDate]).range([0, graph_width]);
var chart = d3.select(location).append("svg")
.attr("class", "chart")
.attr("width", graph_width+20)
.attr("height", graph_height+20)
.call(d3.behavior.zoom().x(x).scaleExtent([1, 8]).on("zoom", zoom));
var lines = chart.selectAll("line");
var lines_y = lines
.data(x.ticks(5))
.enter().append("line")
.attr("x1", x)
.attr("x2", x)
.attr("y1", function (d) {return graph_height - 20 - d;})
.attr("y2", graph_height)
.style("stroke", "#ccc");
var lines_x = lines
.data(y.ticks(10))
.enter().append("line")
.attr("x1", 0)
.attr("x2", graph_width)
.attr("y1", y)
.attr("y2", y)
.style("stroke", "#ccc");
xAxis = d3.svg.axis().scale(x);
yAxis = d3.svg.axis().scale(y).orient("left");
chart.append("svg:g")
.attr("class", "xaxis")
.attr("transform","translate(0,300)")
.call(xAxis);
chart.append("svg:g")
.attr("class", "yaxis")
.attr("transform", "translate(25,0)")
.call(yAxis);
var rect = chart.selectAll("rect")
.data(data)
.enter().append("rect")
.attr("x", function (d,i) {return x(new Date(d["date"]))+20; })
.attr("y", function (d,i) { return graph_height - (d["num"] *v_scale);})
.attr("width", x(new Date(data[1]["date"])))
.attr("height", function (d,i) {return d["num"]*v_scale;});
rect.call(d3.behavior.zoom().x(x).scaleExtent([1, 8]).on("zoom", zoom));
function zoom() {
chart.select(".xaxis").call(xAxis);
chart.select(".yaxis").call(yAxis);
}
}
I feel like I should be adding more functionality to my zoom function for the function to be effective on bars(rects). I would really appreciate any help.
Using 'selectAll', I've applied the scaling and translation to each bar respectively, restricting both scale and translation to the x-axis only.
function zoom() {
chart.select(".xaxis").call(xAxis);
chart.select(".yaxis").call(yAxis);
chart.selectAll(".chart rect").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");
}
This works equally well with a single path element, which is what I was trying to figure out when I stumbled upon your question.
I'm wondering the same thing, so at least know you're in good company. Here's my current approach. First of all, I can't generate a plot from your code and the links don't send me to anything useful -- no chart renders. So I can't help with your specific problem. However, there is an example that has zoomable rectangles here: http://bl.ocks.org/1962173. I'm currently going through it and deleting unnecessary elements and seeing if I can make it work. Hopefully this helps!

Resources