How to fix the d3 object? - javascript

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

Related

SVG out of viewBox should be zoomable

Hi I am trying really hard to solve this problem. Initially I have an svg-element and inside of it a g-element to make zooming in D3 also possible in Safari. I append a D3 Force-Directed Graph to that g-element after generating it. Zooming works perfectly fine so far.
The Force-Directed Graphis generated as preserved here: https://observablehq.com/#d3/disjoint-force-directed-graph
Initial svg-element created:
svg.value = d3
.select("#network")
.append("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.append("g");
Adding the chart:
d3.select("#network").selectAll("svg g > *").remove();
d3.select("#network").select("svg g").node().append(chart);
And the zoom-function afterwards:
const svgZoom = d3.select("#network svg");
const g = d3.select("#network svg g");
svgZoom.call(
d3
.zoom()
.on("zoom", function () {
g.attr("transform", d3.zoomTransform(this));
})
);
Now the issue is that the graph always gets cut. I already tried visibility:visible on each of those elements, still not working. Even if I set a viewBox much bigger than the actual content, or if I set the size of the graph to a minimum, the graph will always get cut to a rectangle.
What I want to accomplish is add the graph full-size and by zooming out the overflowing elements get visible. I do not want to get the height and width of the container and minimize the size of each graph drawn, because some graphs are much bigger than the other ones and I want to keep the initial size of the nodes.
How it currenty looks
Without Zooming Out
Zooming Out
The graph itself cuts the boundaries, adding overflow:visible to the Force-Directed Graph solved the problem.

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.

Scale / Redraw d3.js gridlines on zoom / drag

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)

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

D3.js clip paths cut off the edge of my graph

I have set up a clip path on a D3.js zoomable focus and context graph, but have a slight problem. http://nestoria.darkgreener.com/v2/
The clip path is cutting off some circles from the edge of the focus graph - you'll see that the top and right-hand circles are only half there!
It works well on zoom, though, as you'll see if you click and drag the context graph.
So I'm not sure how to create a clip path that doesn't cut off the edges of these circles. This is my code:
focus.append("defs")
.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width - 200)
.attr("height", height);
var focus_dots = focus
.selectAll(".dot")
.data(mydata[j].data);
focus_dots.enter()
.append("circle")
.attr("clip-path", "url(#clip)");
Any ideas? Your help would be very much appreciated as I'm completely baffled about what to do here!
If you don't want the clipping to not be applied when hovering you can use a stylerule like this:
circle:hover { clip-path: none; }
I had the same problem and got around it using
.attr("transform", "translate(0,-20)")
.attr("height", height+20)
The Idea is a bit hacky, but if you simply move the clipping window up and add the same amount to its height, it should show (in the above case) 20px more on top. (same for left side; concerning the right and bottom side: simply add some pixels to hight/width).
I've used "transform",and the circles were cut to quarter.So use cx and cy instead, problem solved..

Categories

Resources