I'm working with this example, but am struggling to find how to format the x axes to prevent overlap. I believe some of the difficulties I'm experiencing are due to the brush for the zoom/pan option. I'm trying to move the August labels to the right so they don't overlap the y-axis. Additionally, the brush labels completely overlap each other and I'd like to fix that as well.
x-axis code
this.xAxisTop = d3.svg.axis().scale(this.xScale).orient("bottom");
this.xAxisBottom = d3.svg.axis().scale(this.xScale).orient("top");
brush code
context.append("g")
.attr("class", "x brush")
.call(brush)
.selectAll("rect")
.attr("y",0)
.attr("height", contextHeight);
I've tried modifying the x-axis directly by selecting an x-axis and calling .ticks(5), but all it does is return a bunch of code related to the axis functions.
Please let me know if I should include more coherent explanations or examples, thanks!
For this problem we have to write custom tick format functions.
Same problem occurred while zooming is solved in below link.
http://stackoverflow.com/questions/20010864/d3-axis-labels-become-too-fine-grained-when-zoomed-in
Below link helps you in solving your problem directly
http://jsfiddle.net/BdGv5/3/
Three custom javascript functions helps you to change your axis format.
Related
I just started using d3.js yesterday and i have some trouble getting my stuff done.
For now I created a chart with two y axes, each showing some values and an x axis showing dates.
On click on the values on the y axes, I display the corresponding horizontal grid lines.
My problem is, that when zooming in or out, or dragging, the gridlines (horizontal and vertical) don't scale correctly with the axes values, they just don't move at all.
I searched a lot this afternoon and found some examples how to do it, but none of them seem to work with the code i already have.
I presume, that the logic should be added to the zoom behavior but i'm not sure
// x axis gridlines
function make_x_gridlines() {
return d3.axisBottom(x)
.ticks(5)
}
// add the X gridlines
let xGrid = svg.append("g")
.attr('class', 'grid')
.attr("id", "grid")
.attr("transform", "translate(0," + height + ")")
.call(make_x_gridlines()
.tickSize(-height)
.tickFormat("")
)
//zoom behavior
function zoomed() {
.. some behavior ..
//redraw gridlines here?
.. some behavior ..
}
Please see this fiddle for the whole thing.
I called the second y axis (right) zAxis even if it's not a z axis.
Help would really be greatly appreciated.
The axes are working when you zoom. That's because, in the function zoomed() you are updating the scales.
So in order to make the grids zoom, you just need to update its scales too. Put this code inside the function zoomed() and it should work.
xGrid.call(
d3.axisBottom(x)
.scale(d3.event.transform.rescaleX(x))
.ticks(5)
.tickSize(-height)
.tickFormat("")
)
Now you just need to replicate this scale update to all other grids. Sorry that I couldn't give you a complete answer, but I don't have much time right now.
Now, in my opinion, you should not have the function make_gridlines() because it is really simple, and when you're working on lots of updates on different places it confuses me.
So, instead of calling make_gridlines() you call d3.axisBottom(x).ticks(5).
(Note that I'm new to d3 and js, so I'm recommending this based on my little experience and knowledge)
I tried http://bl.ocks.org/godds/ec089a2cf3e06a2cd5fc
However, I found when I used the brush, the main part of the stacked bar is out of boundary. How to fix it?
I think here is the reason:
some bars should not be shown in the main part but they are still in the scope of svg
Thank you for your help!
These types of zoom literally are just geometric zooms, all the bars are still being drawn, it's just that the vast majority are off-screen, some are within the chart limits and a few lie in the axis gap in-between which are the ones that look awkward.
Make a svg clip, and add it to the right 'g' element to get rid of this effect:
svg.append("defs").append("clipPath")
.attr("id", "myclip")
.append ("rect")
.attr({x: 0, width: width, y: margin.top, height: height});
... and later on in the code
// draw the bars
main.append("g")
.attr("clip-path", "url(#myclip)")
.attr("class", "bars")
I’m new to to d3 and have combined mbostock’s stacked bar graph example ( http://bl.ocks.org/mbostock/3886208 ) with a map to show data (canada.json)
I would like the graph to display an updated chart on the d3.mouseover event of the province:
http://gao8a.github.io/ (something like this)
Unfortunately, I was only able to get the axises to display. It's showing either multiple or the same axis overlapping:
(These will take ~ 3 seconds to load)
Multiple:
http://bl.ocks.org/GAO8A/566e238a72e5ebd1e2c1
Same Axis overlap
http://bl.ocks.org/GAO8A/64f94bb494c4a73f2bf6
I understand I probably need a ‘mouseout’ event to delete the previous but I’m not quite sure how to design that either.
Can anyone point out what I’m doing wrong and how I should be loading the data?
PS:
I was going to make a jsfiddle but can’t seem to get it to get it to work with my hosted canada.json data.
https://raw.githubusercontent.com/GAO8A/GAO8A.github.io/master/canada.json
Thanks
Your issue is that you keep adding the axes in the tooltip element. Unfortunately this creates the overlaps. What you could do is add the axes once, and the readjust their domain with the new values that correspond to the element being hovered.
So in essence if you could add the following lines:
var X_AXIS = tooltip.append("g").attr("class", "x axis x-axis").attr("transform", "translate(0," + height + ")");
X_AXIS.call(xAxis)
X_AXIS.append("text").attr("dy", "3em").attr("dx", "50em").style("text-anchor", "end").text("Month");
var Y_AXIS = tooltip.append("g").attr("class", "y axis y-axis")
Y_AXIS.call(yAxis)
Y_AXIS.append("text").attr("transform", "rotate(-90)").attr("dy", "-3em").attr("dx", "-8em").style("text-anchor", "end").text("Temperature (Celcius)");
just before adding your map, this would in a sense 'initialize' the axes.
So further, in your mouseover handler, you could add the following lines, just after you determine your x and y domains.
X_AXIS.call(xAxis)
Y_AXIS.call(yAxis)
or better still, to add some transition:
X_AXIS.transition().duration(400).call(xAxis)
Y_AXIS.transition().duration(400).call(yAxis)
This way, you don't keep adding axes, you just readjust the ones currently intialized.
Hope this helps.
I'm trying to teach myself D3 with examples from http://bl.ocks.org/mbostock.
I took the scatterchart and I'm trying to load various data depending on what menu-item is active.
Everything is working fine, but I got one problem I just can't solve.
The xAxis should update itself depending on the values from the data linked to the menu item.
I was searching the web for an answer, but couldn't find one that worked for me.
I think the problem (and solution) lies in this part of the code;
function updateChart() {
svg.selectAll('.dot')
.transition()
.duration(1000)
.attr('cx', function(d) {
return x(d.data[parameter]);
})
svg.select(".x.axis")
.call(xAxis);
}
I made this JSFiddle to make it more understandable.
Here's what's going on.
You successfully generated your xAxis with the correct x scale in the first go around, however
You didn't update your xAxis with the new domain of data
You were right in that you had to re-update your scales whenever you click on your labels.
I've done a couple of things:
Add a sourceData variable after you've coerced your numbers, for all your functions to reference
Add a updateXScale(data) function that will simply update your x scale's domain
Have it called every time you click a label. Not only will this fix your x scale, it will also enable the correct scaling of your x-coordinates for your .dot's.
Here's what it looks like all together. I've created a fiddle that has a working version of your example.
And here's your updateChart function for reference:
function updateChart() {
updateXScale(sourceData);
svg.selectAll('.dot')
.transition()
.duration(1000)
.attr('cx', function(d) {
return x(d.data[parameter]);
});
svg.select(".x.axis")
.call(xAxis);
}
I'm fairly sure if I can find an example showing what I'm trying to do, I can reverse engineer/reimplement it. Has anyone seen an example showing a smooth/animated transition between a linear and log scale in D3JS?
I have both scales working independently, but I have to reload the page to change the scale.
My Google skills have failed me!
Thanks so much.
Here's a proof of concept jsfiddle. You simply reselect the data points and redraw them with the new scale. For the axis labels, the transition is even simpler -- you just need to call the axis function again. Relevant excerpt below.
// change to log scale...
yScale = d3.scale.log().domain([1, 100]).range([dim-padding,padding]);
svg.selectAll("circle").data(data)
.transition().delay(1000).duration(1000)
.attr("cx", function(d) { return xScale(d); })
.attr("cy", function(d) { return yScale(d); });
svg.selectAll(".y")
.transition().delay(1000).duration(1000)
.call(yAxis.scale(yScale));
You might need to play around with how the labels are generated to make it look "nice", but in principle d3 will take care of the entire transition.