javascript - placing a rectangle under another element - javascript

I have text, and I used a bbox to be able to add a rectangle to match the size of the text.
When I draw the rectangle it is the correct size, but the rectangle is on top of my text.
Is there a way to put the rectangle under the text?

You can use D3's insert to place the <rect> before the <text> in the SVG structure. For example:
svg.insert("rect", "text")
.attr("x", bbox.x)
.attr("y", bbox.y)
.attr("width", bbox.width)
.attr("height", bbox.height)
.attr('class',"rectFillBox")
.attr('fill','white')
.attr("fill-opacity", 0.5);

Related

d3.js is not showing icons

i have been trying to insert an icon using d3.js.but i am not getting any icon when i am running it .here is my code snippet.
node = svg.selectAll('g.node')
.data(svg_nodes, function (d) {
return (d && d.svg_id) || d3.select(this).attr("id");
})
node.select('polygon:nth-of-type(8)')
.append("image")
.attr("xlink:href", "https://github.com/favicon.ico")
.attr("x", -8)
.attr("y", -8)
.attr("width", 16)
.attr("height", 16);
It appears you are appending an <image> to a <polygon>. An image is not a valid child of an SVG polygon, only animation elements or descriptive elements are valid children (MDN).
Permissible children include:
<animate>, <animateColor>, <animateMotion>, <animateTransform>, <discard>, <mpath>, <set>, <desc>, <metadata>, <title>
As you can't add an image to a polygon, you'll need to add it to a different parent, this also means positioning it separately.
Generally speaking, a useful approach here is often to use a parent g to position each polygon and image pair - this might remove the need to position image and polygon separately, but also keeps these elements paired as siblings of a common parent.
As it appears you already have a parent g, we only need to access it in order to append to it:
node.select('polygon:nth-of-type(8)')
.each(function() {
d3.select(this.parentNode)
.append("image")
.attr("xlink:href", "https://github.com/favicon.ico")
.attr("x", -8)
.attr("y", -8)
.attr("width", 16)
.attr("height", 16);
})
Without seeing more of your code it is not possible to say how this will position the image relative to what you want, but should at least append the image

Brush functionality in my d3 line chart is not working as expected

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.

D3.js SVG image bounding box offset

I am attempting to fill a div with an svg image using D3.js. So far I have been able to center my image and watch it scale as I grow and shrink the browser window. However when attempting to dynamically find the bounding box of image I can only find the top,left properties of the canvas and the width of all the space no just my original image.
Here is a basic mock up of my problem:
http://jsfiddle.net/wnwfn/79/
d3.select("#svgEmbed").append("image")
.attr("xlink:href","http://www.clipartkid.com/images/32/square-clip-art-black-and-white-clipart-panda-free-clipart-images-UkJ6sF-clipart.png")
.attr("width", "100%")
.attr("height", "100%")
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.3.12/d3.min.js"></script>
<p>
<svg id="svgEmbed" height="100%" width="100%" ></svg>
</p>
So my question is how can I find the top left position of the square image in this example? I've had a play using the .offset(), .getBBox() but I can't seem to get the values I am looking for.
Your approach isn't going to work. By setting the image width/height to 100%, the image element will always be positioned at [0,0]. If you know the pixel size of how you want the image to display, you can do something like this:
var imgSize = 150;
var img = d3.select("#svgEmbed")
.append("image")
.attr("xlink:href", "http://www.clipartkid.com/images/32/square-clip-art-black-and-white-clipart-panda-free-clipart-images-UkJ6sF-clipart.png")
.attr("x", "50%")
.attr("width", imgSize)
.attr("height", imgSize)
.attr("transform", "translate(" + (-imgSize / 2) + ", 0)");
d3.select(window).on("resize", function(){
console.log(img.node().getBBox());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<p>
<svg id="svgEmbed" height="100%" width="100%"></svg>
</p>

Multiple drag functions on d3 force drag layout

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/

d3 - required help in brush extent()

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

Categories

Resources