Scale / Redraw d3.js gridlines on zoom / drag - javascript

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)

Related

Issue with rectangles not drawing equal with yaxis labels in d3v4

I am new to d3v4 and working on a chart where i need to show little rectangle on certain date matching to its title on yaxis. The problem i am facing is rectangles in the chart area not drawing equal to the yaxis point labels, i have tried changing the y value by hardcoding, it works fine but the point is the number of data object will change in real time like it could be any number of objects in an array. Here is the plunker
To draw the graph dynamically with limited data objects i've created few buttons on top of chart so that rectangles in the chart can draw equal to y-axis labels.
Any help is much appreciated.
You are using a band scale: that being the case, you should not change the y position, which should be just...
.attr('y', function(d) {
return yScale(d.title);
})
.. and you should not hardcode the height: use the bandwidth() instead:
.attr('height', yScale.bandwidth())
The issue now is setting the paddingInner and paddingOuter of the scale until you have the desired result. For instance:
var yScale = d3.scaleBand().domain(data.map(function(d) {
return d.title
}))
.range([height - 20, 0])
.paddingInner(0.75)
.paddingOuter(.2);
Here is the plunker with those changes: https://plnkr.co/edit/ZxGCeDGYwDGzUCYiSztQ?p=preview
However, if you still want (for whatever reason) hardcode the height or the width of the rectangles, use a point scale instead, and move the y position by half the height.

How to fix the d3 object?

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")

How do I modify ticks and format labels on D3 axes?

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.

How to transition D3 axis without tick text attribute reset?

I have a D3 project where I'm drawing a time axis along the left side of the screen. I want to have it smoothly transition on window resize so I'm using D3 transitions. However the axis setup appears to be changing the "dy" attribute on the tick labels immediately causing the tick labels to jump downward and then transition back into their normal place any time the SVG is transitioned. Is there any way to set the "dy" attribute of the tick text as part of the axis call or a better way to transition?
My initial (one-time) axis setup:
var timeScale = d3.time.scale().domain([minTime, maxTime]);
var yAxis = d3.svg.axis().scale(timeScale).tickFormat(d3.time.format("%-m/%-d %-I:%M%p")).orient("right");
I have a function to update/transition the SVG elements I'm using. The first time the SVG is drawn init is set to true, false afterwards.
function updateSVG(init) {
...
timeScale.rangeRound([topPadding, svgHeight]);
// Use a transition to update the axis if this is an update
var t = (init) ? svgContainer : svgContainer.transition().duration(750);
// {1}: Create Y axis
t.select("g.axis").call(yAxis);
// {2}: Move Y axis labels to the left side
t.selectAll("g.tick > text")
.attr("x", 4)
.attr("dy", -4);
...
}
On an update at {1} tick labels all have a "dy" attribute of "-4" from the previous attr() call. At {2} applying the axis resets the "dy" attribute of these elements to a default of ".32em" after which they transition slowly back to "-4" causing them to jitter up and down as the window is resized and the axis is redrawn.
Here is a working JSFiddle that demonstrates the jump on the y-axis when the Result box is resized, resize just by a few pixels and it should be obvious: http://jsfiddle.net/YkDk4/1/
Just figured this out. By applying a "transform" attribute instead of a "dy" attribute the axis call() does not overwrite the value. So:
t.selectAll("g.tick > text")
.attr("x", 4)
.attr("dy", -4);
becomes:
t.selectAll("g.tick > text")
.attr("x", 4)
.attr("transform", "translate(0,-4)");
and everything transitions smoothly.
According to the bug fix made in response to this problem with the text-anchor attribute:
How to tweak d3 axis attributes when transition is present?
It looks like the dy attribute is supposed to update immediately during transitions...but it's not.
In any case, the easiest solution is simply to take the dy update OUT of the transition and apply it directly:
t.select(".y")
.call(yAxis);
chartSvg.selectAll(".y g.tick > text")
.attr("dy", -4);
That should avoid the "bounce".

nvd3.js cumulativeLine Chart translate axis not working (interactive scope issue?)

I'm trying to make a custom chart starting with the Cumulative Line Chart http://nvd3.org/ghpages/cumulativeLine.html
I'd like to display data with origin being top left so I swapped the y range, and now the x axis is on top and I need to translate it to the bottom.
I'm trying to use the common d3js transform attribute
.attr('transform', 'translate(0,' + height+ ')');
as suggested here but it does not seem to be working!
I located this section in the cumulativeLineChart model (around line 350)
g.select('.nv-x.nv-axis')
// .attr('transform', 'translate(0,' + y.range()[0] + ')');
.attr('transform', 'translate(0,' + 300 + ')'); // my testing alteration
d3.transition(g.select('.nv-x.nv-axis'))
.call(xAxis);
Y axis can't be translated either. I think it has something to do with the indexLine and the way the scope can be adjusted, but I may be completely off. In fact, I want to get rid of the interactive indexLine feature altogether...
Am I even modifying the right part of the NVD3 code?!
Any help would be GREATLY appreciated. I've spent hours and hours trying to get the whole thing work (occasionally running back and forth between nvd3 and d3), and I am stuck. Thanks!

Categories

Resources