SVG foreign object is not getting displayed using D3 - javascript

I am using D3 render a simple network diagram. And in each node I want to display html content for that foreign object is used. Foreign object is having html inside. The network is getting rendered. But I am not able to view the html content anybody know why it is not rendering the html?
I am using below code.
dom.svg.selectAll('.node').append("foreignObject")
.attr("width", 100)
.attr("height", 100)
.append("xhtml:body").append("xhtml:p")
.style("color", "red")
.text("Object in SVG");
Here is the fiddle

You can't append foreignObjects (or indeed anything) to circle elements. Instead, append them to a container element like gs for example. Fixed here.

Related

Appending imgs to d3 force graphs

I'm trying to create a d3 force graph with countries' flags, using a spritesheet for the imgs.
I guess I'm still having a hard time understanding d3 syntactically. I was going to use a background-image from a css flag class, and then the subimages would have background-positions. However, adding an img with a class, as in:
var nodesDrawn = d3
.select("#container")
.selectAll("img")
.data(nodesData)
.enter()
.append("img")
.attr('class', function(d){return "flag flag-"+d.code;})
;
produces images, but doesn't work with the force graph... force nodes without links
Alternatively I have produced the graph itself, and do have nodes that work, but can't use images instead of svg circles... force links without nodes
var nodesDrawn = svg
.append("g")
.selectAll("img")
.data(nodesData)
.enter()
.append("img")
.attr('class', function(d){return "flag flag-"+d.code;})
;
And you can see that with links but not nodes, I'm trying to append the nodes to an svg, whereas the working images are being appended to the body directly. Can anyone help me understand how this works?
img is an HTML tag, and the graph you're building is SVG. Once you start working inside of a svg tag on a page, you're dealing with SVG elements, not HTML elements.
You can, though,
Put HTML inside of SVG by using the foreignObject tag
Use the SVG equivalent of the img tag, which is the image tag

How to add controls and buttons to map?

This is probably a really basic question, but I can't figure it out. I'm building a map using D3. My code creates and svg, appends a g element to it and then draws the map within it. What I want is to render a set of buttons and controls that are positioned inside the map viewer. They would be zoom buttons, a dropdown to display different sets of data and a timeline slider.
For example, with the dropdown selector I want placed I did this:
I tried using d3 as in:
svg.append("select")
.attr("class", "field_dropdown")
.data(['housing_unit', 'tenure', 'median_contract_rent', 'median_value', 'median_income'])
.enter()
.append("option")
.attr("value", function(d) {
return d
});
but this rendered the select item and option items separate from each other, and not even visible within the map container.
As mentioned, not only do I wanna add a dropdown, but also buttons for zoom and a slider, among other items. How do I render and position them in the map container?
Thanks
This has been asked several times (surely a duplicate): you cannot append HTML elements ("div", "p", "select", "h1" etc) to an SVG. It will simply not work.
The best solution, in your case, is creating the drop down menu and the other controls outside the SVG, in the HTML.
But, if you really want to create this drop down inside the SVG (which I don't advise), you can use foreignObject (which will not work on IE):
var foreign = svg.append("foreignObject")
.attr("width", 100)
.attr("height", 100)
.append("xhtml:body");
var select = foreign.append('select')
.attr("class", "field_dropdown")
//the rest of your code

Images not Generating D3

Here is my problem. My graph currently looks like this: Which is dandy. However, I want the black squares on top to be filled with pictures. Luckily I have a CSS file that has pictures linked with classes. I also have a JSON file that contains all the class names. All those class names are assigned to the squares and I can see the picture in the inspect element on Chrome. The only issue is the pictures don't appear in the square. (Also my axises broke, but that is secondary concern). CSS, JSON
This is where I'm assigning classes and creating the rectangles.
svg.selectAll(".div")
.data(data.chartData, function(d){return d.vNm;})
.enter().append("rect")
.attr("x", function(d){
return x(d.vNm);
})
.attr("y", function(d){
return (y(d.values.reduce(function(sum, d){
return sum + d.amount;
}, 0))) - 64.5;
})
.attr("width", 43)
.attr("height", 43)
.attr("class", function(d){return d.vId;})
.style("fill", function(d) { return segColor(d.data.type); });
One approach to solve your problem is to use html elements like div for the images above the chart instead of svg elements, so you can use the full power of css.
Luckily you don't need to calculate the position of those html elements by yourself, there are some libraries that help you position the images correctly above the bars in the chart.
Check out https://popper.js.org/ for example, you can just call its API for each bar you render using d3.js:
var popper = new Popper(barElement, onPopper, {
placement: 'top'
});
SVG elements do not follow exactly the same CSS rules as typical HTML elements.
In your case, background-image doesn't work.
The least painful way to achieve the effect would be to embed an <image> tag after the <rect>:
<image width="100" height="100" xlink:href="data:image/png;base64,...">
It means that you have to modify your JSON to store the image's base64 data in there instead of CSS.

What is defs in javascript/svg

svg.append("defs")
.append("filter").attr("id", "blur")
.attr("x", "-50%").attr("y", "-50%")
.attr("height", "200%").attr("width", "200%")
.append("feGaussianBlur").attr("in", "SourceGraphic").attr("stdDeviation", 10);
I saw these code in javascript. I try to google, but still can not understand what is a "defs" in js.
BTW, can anyone explain what is a "filter"?
Many thanks!
Looks to me like your code is some implementation of a Gaussian blur filter using SVG. So defs and filter there are really SVG concepts, not so much JavaScript.
defs
SVG allows graphical objects to be defined for later reuse. It is
recommended that, wherever possible, referenced elements be defined
inside of a defs element. Defining these elements inside of a defs
element promotes understandability of the SVG content and thus
promotes accessibility. Graphical elements defined in a defs will not
be directly rendered. You can use a element to render those
elements wherever you want on the viewport.
filter
The filter element serves as container for atomic filter operations.
It is never rendered directly. A filter is referenced by using the
filter attribute on the target SVG element.
feGaussianBlur
The filter blurs the input image by the amount specified in
stdDeviation, which defines the bell-curve.
Documentation from Mozilla
https://developer.mozilla.org/en-US/docs/Web/SVG/Element/defs
https://developer.mozilla.org/en-US/docs/Web/SVG/Element/filter
https://developer.mozilla.org/en-US/docs/Web/SVG/Element/feGaussianBlur

Cannot plot chart using D3.js

I'm learning how to plot charts using D3.js on SVG objects.
My code creates elements in DOM objects, but they do not display.
If I run DOM inspector and copy all elements to another html document and display that the rectangles are visible.
I'm trying to plot two static rectangles on JSFiddle
SVG is case sensitive so you want
svg = d3.select("div#Wykres2")
.append("svg")
.attr("width", szerokosc)
.attr("height", wysokosc)
.text("not work :(");

Categories

Resources