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);
Related
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/
I am using d3 js to draw a bar graph. I have x and y axis too.
The x axis would hold the 'names' and y axis the 'marks'. I am using ordinal scale for x axis.
In my json input dataset_rule_errors, I have 10 entries.
My code is
var svgd = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height);
var x_domain = dataset_rule_errors.map(function(d) { return d.Rulename; })
var xScale = d3.scale.ordinal()
.domain(dataset_rule_errors.map(function (d) { return d.Rulename; }))
.rangeBands([padding_rule, wsvg]);
var xaxeScale = d3.scale.ordinal()
.domain(x_domain)
.rangePoints([padding_rule, wsvg]);
var xAxis = d3.svg.axis()
.scale(xaxeScale)
.tickValues(x_domain)
.orient("bottom");
//drawing rectangles
svgd.append("g")
.selectAll("rect") //based on the data in the dataset[] array, append rectangles s.t.
.data(dataset_rule_errors) //
.enter()
.append("rect")
.attr("x", function (d, i) {
return xScale(d.Rulename); // x position of rect as per i->0,1,2,3,...
})
.attr("y", function (d) {
return (h_rule - yScale(d.NumRuleFailed)); //y position of rect as per (h-value) to prevent inverted range
})
.attr("width", xScale.rangeBand())//"10") //depending upon domain->no of inputs - with of band is decided acc. to fit in svg
.attr("height", function (d) {
return yScale(d.NumRuleFailed); //depending upon domain->value of inputs - with of band is decided acc. to fit in svg
})
.attr("fill", function (d, i) { //colour based on values -> more errors - dark coloured bars
if(i%2==0)
return "rgb(" + 255 + "," + 255 + "," + 200 + ")";
else
return "rgb(" + 0 + "," + 0 + "," + 200 + ")";
})
.attr("stroke", "black");
//drawing x axis with ticks
svgd.append("g")
.attr("class", "x axis")
.attr("transform", "translate(" + 0 + "," + (h_rule) + ")")
.call(xAxis)
.selectAll("text")
.style("text-anchor", "end")
.attr("dx", "-.8em")
.attr("dy", ".15em")
.attr("text-anchor", "start")
.attr("transform", function (d) {
return "rotate(-90)"
})
.selectAll(".tick text")
.style("text-anchor", "start");
The problem I am facing is that my rectangles and the ticks of x-axis do not align with one another.
The reason is because I have 10 bars and therefore, I should be having 11 ticks including the one at the beginning and the end. But I have only 10 ticks, which distribute evenly along the axis length, so they do not coincide with the rectangle beginnings just like in this question Unable to align ticks with d3.js.
But the solution for this question did not work out for me. What can I do?
dataset_rule_errors = data I retrieve from my database
[{"Rulename":"A","NumRuleFailed":34321},{"Rulename":"B","NumRuleFailed":43},{"Rulename":"C","NumRuleFailed":45522},
{"Rulename":"D","NumRuleFailed":43643},{"Rulename":"E","NumRuleFailed":152},{"Rulename":"F","NumRuleFailed":152}]
I could not reproduce the issue you said you were having but I highly recommend using rangeRoundBands for a bar chart.
You can achieve the bar chart with the following setup:
var x = d3.scale.ordinal()
.rangeRoundBands([0, width], .2);
var y = d3.scale.linear()
.range([height, 0]);
// Finding domain of x (all our rulenames)
x.domain(data.map(function(d) {
return d.Rulename;
}));
// Finding domain of y (min and max values)
y.domain([d3.min(data, function(d) {
return d.NumRuleFailed;
}), d3.max(data, function(d) {
return d.NumRuleFailed;
})]);
var xAxis = d3.svg.axis()
.scale(x)
// no need yo specify ticks, x scale
// will take care of that
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left")
And the following for axis and rect rendering:
// Render 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", "-.50em")
.attr("text-anchor", "start")
.attr("transform", "rotate(-90)")
.selectAll(".tick text")
.style("text-anchor", "start")
// Render yAxis
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("NumRuleFailed");
// Render rects
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d) {
return x(d.Rulename);
})
.attr("width", x.rangeBand())
.attr("y", function(d) {
return y(d.NumRuleFailed);
})
.attr("fill", function(d, i) { //colour based on values -> more errors - dark coloured bars
return (i % 2) ? 'green' : 'red';
})
.attr("height", function(d) {
return height - y(d.NumRuleFailed);
});
Full Plnkr: https://plnkr.co/edit/jmtMGcRyT9hM5efwwTOb?p=preview
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!
I am currently trying to transition both the x and y axis on this chart to 'grow out' from the bottom left corner from blank space into the way they currently look:
http://bl.ocks.org/maharlikans/304443d2da3f479e20e3
I want the chart to 'grow out' from the bottom left corner of the screen, mostly just for aesthetic purposes. I thought initially that I could just set the range on each axis to [0, 0] around these lines:
var x0 = d3.scale.ordinal()
.rangeRoundBands([0, width], .3);
var x1 = d3.scale.ordinal();
var y = d3.scale.linear()
.range([height, 0]);
and then call .transition().duration(someduration).range([0, myrange]) around these lines:
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.style("text-anchor", "end")
.text("Count");
but that didn't work. I thought maybe I have the right idea but am executing the code wrong. Could anyone think of a way to do this?
To grow in an axis using a transition would be like this:
// after the rest of the plot is drawn
// y
y.range([height,height]); // set no axis
svg.select(".y.axis").call(yAxis); // draw it
y.range([height,0])
svg.select(".y.axis")
.transition()
.duration(1000)
.call(yAxis); // transition it to "grown"
// x
x0.rangeRoundBands([0, 0], .3);
svg.select(".x.axis").call(xAxis);
x0.rangeRoundBands([0, width], .3);
svg.select(".x.axis")
.transition()
.duration(1000)
.call(xAxis);
You have to do this after the rest of the plot is created since having a range of [height, height] or [0,0] will mess up the placement of other elements.
Example Here
Another possible solution that works on the yaxis and xaxis g elements and does not mess with the .range at all:
svg.select(".x.axis")
.transition()
.duration(1000)
.attrTween("transform", slideX);
function slideX() {
var pos = (500-margin.top-margin.bottom);
var interp = d3.interpolate( -pos * 2 , 0);
return function(t) {
return "translate("+interp(t)+","+ pos +")";
}
};
svg.select(".y.axis")
.transition()
.duration(1000)
.attrTween("transform", slideY);
function slideY() {
var pos = 960 - margin.left - margin.right;
var interp = d3.interpolate(pos * 2, 0);
return function(t) {
return "translate(0," + interp(t) +")";
}
};
Example Here
This example is a little more fun; with this you scale in the axis, rotate, skew it, etc...
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");