I'm drawing a chart but have trouble how to handle my y scale and that my rectangles are drawn "upon" each over. (I draw with the bars from y-axis)
I calculate how high each bar needs to be and if a bar is higher than my default height the y does not manage to handle this. I'm not shure how to handle this. I draw my rect:
forms.append("rect")
.attr("class", "rectStyle")
.style("fill", function(d) { return color(d.Name); })
.attr("x", function(d){ return x(new Date(d.startDate));})
.attr("height",function(d) { return d.barHeight;})
.attr("y", function(d) { return y(d.RowGroup);})
.attr("width", function(d){ d.w = (x(new Date(d.endDate))-x(new Date(d.startDate)));
return d.w; });
y = d3.scale.linear()
.domain([1,noRows])
.range([0,height -margin.top-margin.bottom-padding*noRows]);
Grateful for how I should solve this problem
Related
Looking to stylize a bar chart using a D3 SVG. Right now it contains a number on the y axis and, on the x axis, day by day labels. There is a tick mark for each day, where I want only the first date of the week displayed. How can I show just one a week? Code below:
d3.csv("us-counties-cases.csv", function(data) {
filteredData = data.filter(function(row) {
return row['county'] == 'New York City';
});
var x = d3.scaleBand()
.range([ 0, width])
.domain(filteredData.map(function(d) {
return d.date;
}))
.padding(0.2);
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x))
.selectAll("text")
.attr("transform", "translate(-10,0)rotate(-45)")
.style("text-anchor", "end");
// Add Y axis
var max = d3.max(filteredData, function(d) { return d.cases; });
var y = d3.scaleLinear()
.domain([0, max * 1.2])
.range([ height, 0]);
svg.append("g")
.call(d3.axisLeft(y));
// Bars
svg.selectAll("mybar")
.data(filteredData)
.enter()
.append("rect")
.attr("x", function(d) {
return x(d.date);
})
.attr("width", x.bandwidth())
.attr("fill", "#b3b3b3")
.attr("height", function(d) {
return height - y(0);
})
.attr("y", function(d) {
return y(0);
})
// Animation
svg.selectAll("rect")
.transition()
.duration(200)
.attr("y", function(d) {
return y(d.cases);
})
.attr("height", function(d) {
return height - y(d.cases);
})
.delay(function(d,i){
return(i*50)
})
})
Usually you can use axis.tick() to set the arguments that controls how ticks are displayed. Among other things, you can set how many ticks to visualize.
However, as you can read in the documentation, the effect of this method and its arguments depends on the axis’ scale type. If you are using scaleBand, axis.tick() has no effect and you should use axis.tickValues to set the tick values explicitly. Similarly, if you want to change the tick format, it's necessary to use axis.tickFormat.
For your specific case, the following code modifies the x axis to show only one tick every 7 days:
d3.axisBottom(x).tickValues(x.domain().filter( (d,i) => !(i % 7) ))
I ran into a common problem while making a bar graph in d3: my y-axis was upside down. After some googling, I found out that the best way to fix this is by reversing the y-domain. The only problem is, when I did that, the bars on my graph switched positions, so the largest was at the beginning instead of the end. I need the y-axis to be correct, without changing my bars.
Bars in correct positions, but the y-axis is upside-down
Bars are incorrect, but the y-axis is right-side-up
Here is the code: https://codepen.io/lucassorenson/pen/rPRadR?editors=0010
const yScale = d3.scaleLinear()
.domain([0, d3.max(json, (d) => d[1])])
.range([h - padding, padding]);
const yAxis = d3.axisLeft(yScale);
This is the code that I changed. If you reverse the range ([padding, h - padding]), the bars are correct but the axis is not.
The fix is simply to exchange the callback functions of the attributes "height" and "y".
Your code was:
...
svg.selectAll('rect')
.data(json)
.enter()
.append('rect')
.attr('width', 3)
.attr('height', (d) => yScale(d[1]))
.attr('x', function(d, i){
return i*4 + padding
})
.attr('y', function(d){
return h - yScale(d[1]) - padding
})
change it to:
...
svg.selectAll('rect')
.data(json)
.enter()
.append('rect')
.attr('width', 3)
.attr('y', (d) => yScale(d[1]))
.attr('x', function(d, i){
return i*4 + padding
})
.attr('height', function(d){
return h - yScale(d[1]) - padding
})
With the attribute "y" you typically set the upper edge of the rectangle and with "height" you denote how far it goes down.
var y = d3.scale.ordinal()
.rangeRoundBands([height,0], .1)
var x = d3.scale.linear()
.rangeRound([0, width],.1);
{......}
state.selectAll("rect")
.data(function(d) { return d.ages; })
.enter().append("rect")
.attr("width", y.rangeBand())
.attr("height", function(d) { return x(d.x1)-x(d.x0); })
.style("fill", function(d) { return color(d.name); });
I don't know why my bar rotated 180 degree, I want the y-axes show the bar. So it will look like vertical bar.
Please help! Thank you!
I'm new to D3.js and using following example from D3.js to create a simple dashboard for one of my web application.
http://bl.ocks.org/NPashaP/96447623ef4d342ee09b
My requirement is to rotate top value labels of each bar vertically by 90 degrees.
I changed following method by adding "transform" attribute. Then the labels do not align properly.
//Create the frequency labels above the rectangles.
bars.append("text").text(function(d){ return d3.format(",")(d[1])})
.attr("x", function(d) { return x(d[0])+x.rangeBand()/2; })
.attr("y", function(d) { return y(d[1])-5; })
.attr("text-anchor", "middle")
.attr("transform", function(d) { return "rotate(-90)" });
I tried to find a solution for long time but couldn't. Links to my codes are given below.
https://jsfiddle.net/vajee555/7udmyj1k/
Can anybody please give me an idea how to archive this?
Thanks!
EDIT:
I have solved the problem here.
http://jsfiddle.net/vajee555/7udmyj1k/5/
Remember that when you rotate an element, the x and y coordinates are changed: they are no longer with respect to that of the chart, but with respect to the new rotated orientation of the element. Therefore, you will need to compute the x and y attributes differently.
By rotating -90deg, your x axis will be flipped to y, and the y will be flipped to -x:
I have made some small pixel adjustments to make it appear aesthetically pleasing, such as the +8 I have added to the y coordinate and the +5 I have added to the x coordinate, but the fine tuning is up to you.
// Create the frequency labels above the rectangles.
bars.append("text").text(function(d){ return d3.format(",")(d[1])})
.attr('transform', 'rotate(-90)')
.attr("y", function(d) { return x(d[0]) + x.rangeBand()/2 + 4; })
.attr("x", function(d) { return -y(d[1]) + 5; });
Also, change how the coordinates are calculated in the hG.update() function:
// transition the frequency labels location and change value.
bars.select("text").transition().duration(500)
.text(function(d){ return d3.format(",")(d[1])})
.attr("x", function(d) { return -y(d[1]) + 5; });
See working fiddle here: https://jsfiddle.net/teddyrised/7udmyj1k/2/
//Create the frequency labels above the rectangles.
bars.append("text").text(function(d){ return d3.format(",")(d[1])})
.attr("x", function(d) { return x(d[0])+x.rangeBand()/2; })
.attr("y", function(d) { return y(d[1])-5; })
.attr("text-anchor", "middle")
.attr("transform", "rotate(-90,0,0)" );
Change the last line as above.
I've set the scale of my bar chart with a time domain, from 1985 to 2015. D3 displays it nicely; however, there is an overlapping on some bars. I could reduce their width, but it would be too small. See screenshot here : http://imgur.com/y8QDbqn.
Is there any way to force the bars to align one after the other, even if it requires to cheat a little bit on the alignement?
Some snippets of code:
var x = d3.time.scale()
.range([0, width]);
x.domain(d3.extent(data, function(d) { return d.date; }));
svg.selectAll("bar")
.data(data)
.enter().append("rect")
.style("fill", function(d) { return color(d.parti); })
.attr("x", function(d) { return x(d.date); })
.attr("width", 5)
.attr("y", function(d) { return y(d.nombre); })
.attr("height", function(d) { return height - y(d.nombre); });
(Full code here : https://gist.github.com/992502bf6118da4b7b6b.git)
Thank you!