Here's the fiddle.
When I use the brush, the colored areas start off beyond the x axis defined.
For the line in the graph, I got a suggestion in this SO to add clip-path: url(#clip) to the line css. It works. After applying that, the line starts exactly from the 0 of x when using the brush.
But when I apply the same logic to the css of the .area.above and .area.below, it doesn't work.
The areas are clipped correctly but only one is actually displayed...from inspecting the elements in the browser developer tools, one of the areas is apparently overlaying the other.
Some one help me where I'm making the mistake?
Thanks in advance.
Here's a fiddle which I think does what you want: http://jsfiddle.net/henbox/jzPaq/
The problem was that you can only have one clip-path defined for an element. So adding the rectangular clipPath:
...append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
was over-writing the clip-below and clip-above ones (in <path class="area below"...> and <path class="area above"...> respectively.
The solution I used was based on this info: http://apike.ca/prog_svg_clip.html
For the 'below' I used the intersection of the rectangular (#clip) and 'below' clip paths, like this:
Give the path element an id (clipbelowshape):
focus.append("clipPath")
.attr("id", "clip-below")
.append("path")
.attr("id", "clipbelowshape")
.attr("d", area.y0(height));
Create the intersect of clip clipPath with clipbelowshape:
var clipbelowintersect = focus.append("clipPath")
.attr("id", "clipbelowintersect")
.attr("clip-path", "url(#clip)");
clipbelowintersect.append("use")
.attr("xlink:href", "#clipbelowshape");
Use the new intersect clip path
focus.append("path")
.attr("class", "area below")
.attr("clip-path", "url(#clipbelowintersect)")
.attr("d", area);
Do the same thing with the above path
Related
I've got a choropleth map working with D3 on Observable. When the user mouses over a country, the border (path) is redrawn in red. I'd like to make this border extend on the interior of the path.
Here is the page: https://observablehq.com/d/33b758c361e919e8
This question is similar to Simple way to use existing object as a clipping path? with the difference that the clipping path needs to be set for each country individually. I'm just not sure how to handle that.
In an ideal world I would use the SVG Strokes extension to simply draw the stroke on the inside of the path, as discussed here: Can you control how an SVG's stroke-width is drawn?
I think I've essentially solved this problem by adding clipPath elements which refer to the previous paths (with the "use" tag).
svg
.append("g")
.attr("id", "map")
.selectAll("path")
.data(topojson.feature(world, world.objects.countries).features)
.join("path")
.attr("class", "country")
.attr("fill", d => color(value.get(d.properties.name)))
.attr("id", d => `${d.id}`)
.attr("d", path);
svg
.append("g")
.selectAll("clipPath")
.data(topojson.feature(world, world.objects.countries).features)
.join("clipPath")
.attr("id", d => `${d.id}_clip`)
.append("use")
.attr("xlink:href", d => new URL(`#${d.id}`, location))
My implementation for Brush & Zoom functionality in my d3 line chart is not working as expected,
I followed this link - https://bl.ocks.org/EfratVil/92f894ac0ba265192411e73f633a3e2f,
Problems what I am facing is -
chart is not showing all the values, I have 4 data but it only shows 3 data
onClick of dot I am showing the rect which is not moving with the brush functionality
minor thing but chart always goes out of the box
My code sandbox - https://codesandbox.io/s/proud-firefly-xy1py
Can someone point out what I am doing wrong? thanks.
Please suggest me what I am doing wrong, thanks.
Your first point is going behind your clip area. For example, if you right click on the first visible circle and inspect element you will see all 4 circle elements are present in the dom. The first circle element is behind the axis.
This means you have to move your plot to the right. Unfortunately, the way you have coded the chart you have not appended a g element for the main chart and then appended the circles and path to that g element. As a result this has to be done in multiple places.
First we adjust your clip path as:
svg
.append("defs")
.append("SVG:clipPath")
.attr("id", "clip")
.append("SVG:rect")
.attr("width", containerWidth)
.attr("height", height)
.attr("x", 40)
.attr("y", 0);
next we adjust your circles
scatter
.selectAll(".foo")
.data(data)
.enter()
.append("circle")
.attr("class", "foo")
.attr("transform", "translate(40,0)")
and then your line
scatter
.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line)
.attr("transform", "translate(40,0)");
You will have to account for this 40 px translate for your other elements as well. Although I am having a hard time destructuring your svg. I think this should give you the idea though. Check the axis matches the time points as well.
Check the code sand box
Update
To make the rectangles move with the brush, you will have to add code to your brushed const function to recalculate the x, y, width and height using the updated scales.
Update2
After going through the codesandbox presented in the comments I was able to add the code to update the rectangles to the brushed const as below to make the rects also move with the brushing:
// update rectangles
scatter
.selectAll(".rect-elements")
.attr("x", d => {
console.log(d);
return xScale(d.startTime) - 12.5;
})
.attr("y", 0)
.attr("width", 24)
.attr("height", height + 5);
Full working Code Sandbox.
tried to create a scatterplot which can be zoomed but only the axis is getting zoomed and not the data. Not able to figure out whats wrong anybody any help with this one?.
github link of project : scatterplot with zoom
I see two separate issues with the way the zoom is working:
You are not selecting the <circle>s (points in the scatter plot) correctly when zooming. Consequently when you zoom only the axes are changing (as you described). An easy way to fix this is to give each <circle> a class (e.g. class="dot"), and then use that to select them.
First add the class="dot" to each of your circles (line ~140):
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
Then update the function zoom to select them correctly (line ~195):
svg.selectAll(".dot") // <---- select all circles with class "dot"
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); });
Right now the zoom only occurs when you try to zoom in on an axis or individual point. If you want a user to be able to zoom in no matter where their mouse is over your scatter plot, you can add a background <rect> that will make sure the zoom event is detected for the SVG.
svg.append("rect")
.style("fill", "#fff")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
Making these two changes fixes the zoom.
I have the following layout:
Gray side: the main container (zoom, pan)
White circles: d3 nodes (mousedown, mouseup, drag)
Red rectangles: rectangles (drag, without container panning)
When dragging the red rectangles, I don't want to drag the main container too.
Also, when zooming, they should'n be affected.
I think that the issue is related to:
// Add rectangle for pan handlers
containerParent.append("rect")
.attr("width", SVGWidth)
.attr("height", SVGHeight)
.style("fill", "none")
.style("pointer-events", "all");
JSFIDDLE
By moving the code snippet from your post before appending g element containing starter elements, the issue is fixed:
...
// Add rectangle for pan handlers
containerParent.append("rect")
.attr("width", SVGWidth)
.attr("height", SVGHeight)
.style("fill", "none")
.style("pointer-events", "all");
// Add starter elements and their container
var starterElmsParent = containerParent.append("g");
...
Fiddle: http://jsfiddle.net/praveenscience/88gL4aks/
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..