Appending imgs to d3 force graphs - javascript

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

Related

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.

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 :(");

How to embed bitmap into D3js generated SVG code?

Given access to suitable topojson and bitmaps, I use the topoJSON file to generate a SVG viz via D3js. Then I append a bitmap to it via :
// Append bitmap
svg.append("image")
.attr("xlink:href", "./myimage.png")
.attr("width", width)
.attr("height", height)
.attr("class", "bg");
But this actually just add a link toward the image. Also, when I select the dataviz DOM, and save it as SVG, I don't have the bitmap binary, but just the bitmap's link.
Is it possible, and how to really embed my .png binary into my SVG DOM via D3js or javascript ?
See also: https://rugger-demast.codio.io/front/_location_map-en-wikiatlas.html , where you can try to download the SVG.
This example shows how to draw an image to a canvas element and use the .toDataURL function to get a snapshot of this canvas into a string that you can then use as the xlink:href attribute:
http://bl.ocks.org/emeeks/707681f1f5b4a2063d6e

SVG foreign object is not getting displayed using D3

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.

Implementing <div> tooltips via d3 within an <svg> container

I'm relatively new to D3, svg, and javascript in general, so please bear with me :]
I have been experimenting with D3 for creating plots and graphs. I have created a small plot using D3 and have been attempting to make it compatible with IE8. Here is a link to the more-or-less working build of my graph.
http://jsfiddle.net/kingernest/YDQR4/1/
After some research, I quickly realized that the only way running D3 on IE8 would be at all feasible is by using other APIs in conjunction with D3. Luckily, I found that someone had already put in some work into a project called "r2d3" which, from my understanding, uses raphael to paint the canvas on the IE8 window instead of using SVG (which apparenly was not supported in IE8).
I have been able to get items drawn on the screen, which is half the battle. However, I'm having many issues, particularly with my tooltip. My tooltip is written as a DIV container that floats and changes position/opacity on hover of the data circles. This seems to work fine in other browsers, but with r2d3, I have not been able to get it working. I suspect this is because of the fact that I am creating the div tooltip outside of the (in the #main div). However, I have tried placing tooltips inside of the SVG container with no avail. I then did more reseach and discovered I would have to wrap a div container inside a tag, but after some experimentation with this, I still wasn't able to get the tooltip to work correctly in IE. I attempted to wrap the in a SVG group (), and altered the positioning of this object instead, but this did not seem to work either, and simply through numerous exceptions when trying to append the foreignObject tag to a group.
At this point I'm sort of stuck, and was wondering if anyone had any suggestions as to how I may be able to successfully implement the tooltips. I've also noticed that using d3.select(this) inside my functions, when attempting to select a particular data point (in this case, a circle) seems to present a number of issues when attempting to access or modify that item's attributes, but I think this is a whole other issue entirely.
Any help is greatly appreciated!
Example of how I'm currently creating the tooltips:
//Create tooltip element
var tooltip = d3.select("#main")
.append("div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("opacity", 0);
function mousemove()
{ //Move tooltip to mouse location
return tooltip.style("top", (event.pageY-10)+"px").style("left",(event.pageX+10)+"px");
}
//Mouseover function for circles, displays shortened tooltip and causes other circles to become opaque
function mouseover()
{
var myCircle = d3.select(this);
d3.select(this).attr("class", "dataCircleSelected"); //Color circle green
tooltip.html( //Populate tooltip text
"Username: " + d3.select(this).attr("username") + "<br/>" +
"Session ID: " + d3.select(this).attr("sessionid") + "<br/>" +
"Impact CPU: " + d3.select(this).attr("impact")
)
.transition()
.duration(250)
.style("opacity", .7);
//After 1000ms, make other circle opaque
svg.selectAll("circle")
.filter(function(d, i){ //return every other circle
return !d.compare(myCircle[0][0].__data__);
})
.transition().delay(1000)
.style("opacity", .2);
}
Have you tried using foreignObjects AND explicitly using the xhtml namespace for html tags in the foreignObject (write xhtml:div instead of div) as explained here: HTML element inside SVG not displayed ?
This would give something like that for the tooltip definition
var tooltip = d3.select("#main").append("foreignObject")
.append("xhtml:div")
.attr("class", "tooltip")
.style("position", "absolute")
.style("z-index", "10")
.style("opacity", 0);

Categories

Resources