Positioning multiple SVG elements in div HTML - javascript

I have 2 charts which looks like this:
I need to display the tag-cloud next to the bar-chart. I am using D3 to display these charts and my HTML division looks like this (svg1 displays bar-chart and svg2 displays tag-cloud):
I would appreciate any help. Here is the DEMO. In the demonstration I want circle to appear next to the bar chart.
Thanks!

Why not just float the elements like here on your demo
d3.select("body").append("div")
.attr("id","area1")
.style("width", 500)
.style("float","left");
And
function wordCloud(){
var wC = {};
d3.select("body")
.append("svg")
.style("float","left")
.attr("width", 50)
.attr("height", 50).append("circle").attr("cx", 25).attr("cy", 25).attr("r", 25).style("fill", "purple");
return wC;
}

Related

How can I append the one SVG (graph) inside another SVG node (rect) after onclick using d3.js?

I want to populate the data inside the parent graph node, that is I want to add nested svg on click event using d3.js.
I have tried following code but the output is looking very different I want to show the graph inside the after on click event of first svg node.
var svg = d3.select("body").append("svg")
.attr("width", 600)
.attr("height", 400)
svg.append('rect')
.attr('class', 'content shape')
.attr("width", 20)
.attr("height", 20)
.attr("stroke", "black")
.attr("stroke-width", 1)
.style("fill", function (d) {
return d._children ? "lightsteelblue" : "#fff";
})
.on("click", createMap);
var createMap (mapData){
if(mapdata.data){
d3.select(this).attr("width", 200)
.attr("height", 200)
.call(function(d){
var nodeMap = getGeneratedmap(mapdata.data);
return nodeMap
}
}
}
var getGeneratedmap(mapdata){
var generatedmapSVG = d3.select("#subnodeMap").append("svg")
....
....(logic for map generation)
....
return generatedmapSvg
}
<body>
<div id="mainMap">
<svg></svg>
</div>
<div id="subnodeMap"></div>
</body>
Please guide me and give the proper way to solve the above issue. Thanks in advance.
Your first SVG, the var svg is being appended to <body>. The second SVG is being appended to the div with ID #subnodemap, so you are not actually nesting the first SVG inside the second. You probably want to do something like:
var generatedmapSVG = svg.append("svg")
That's about as much as I can help you without a working example in Codepen or similar, hope it gets you towards a solution.

d3 + drawing svgs + incorrectly overwriting

this i my jsfiddle that shows 2 piecharts which gives me something like this in the html view:
<svg width="220" height="220">
<svg width="220" height="220">
this is my fiddle where I am trying to insert an svg before the 2 piecharts, but I am not writing it correctly, 1 of the pie charts gets over written.
Can anyone advise how I can have all 3 svgs showing?
All my code as it is in the 2nd fiddle
var width = $(document).width()-50 || 960,
height = $(document).height()-50 ||500;
//attaches/appends a svg tag to a body tag with a width and height
/* COMMENT IN */
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
data=[[10, 5],[32, 24]]
z = d3.scale.category20c();
//attaches/appends a svg tag to a body tag with a width and height
var svg2 = d3.select("body").selectAll("svg")
.data(data)
.enter().append("svg:svg")
.attr("width", 220)
.attr("height", 220)
.append("svg:g")
.attr("transform", "translate(" + 100 + "," + 100 + ")")
svg2.selectAll("path")
.data(d3.layout.pie())
.enter().append("svg:path")
.attr("d", d3.svg.arc()
.innerRadius(10)
.outerRadius(100))
.style("fill", function(d, i) { return z(i); });
NOTE: Some further background is that the first svg is a map that I have working. And What I am trying to do is create a layer on top of this which will be piecharts, in this case just 2, but you have to start somewhere :)
Your interpretation of the results is slightly wrong. The first pie chart doesn't get overwritten, it won't get rendered in the first place. In the commented in version you are appending the svg for your map, which works fine and can easily be identified by the width and height values assigned to it.
When trying to append the SVGs for your pie charts, you are selecting all SVGs in the body by doing d3.select("body").selectAll("svg"). This selection will include the previously appended SVG. You are then binding your data to the selection which will compute the data join. Since you are binding an array of data without any key function the join will be based on the index. Thus, the existing SVG will correspond to the first element in the data array and will be put to the update selection. As your code only works on the enter selection the first pie chart will never be drawn because it doesn't belong to this selection. The second one is output as expected.
One way to work around this is to use a CSS marker class for the pie charts. That way you could limit the second selection to the SVGs having the marker class:
var svg2 = d3.select("body").selectAll("svg.pie") // select with class "pie"
.data(data)
.enter().append("svg:svg")
.attr("width", 220)
.attr("height", 220)
.classed("pie", true) // set marker class for all pie charts
.append("svg:g")
.attr("transform", "translate(" + 100 + "," + 100 + ")")
Because no SVG is present having class pie, all your data will end up in the enter selection rendering an SVG containing a pie chart for every data element as expected. I have updated your JSFiddle to show the effect.

Displaying labels on horizontal chart with d3.js

I'm creating a simple chart with d3.js using the following code. Now suppose the var data is properly formatted (ex. "[20,15,15,40,10]"), the horizontal chart displays properly but I'd like to add some labels on the left and I'm a bit overwhelmed by d3.js . I was trying to insert an extra div containing the label before every other div representing and showing the data, but I can't understand how or if that's the proper way.
The result should look something like:
Label 1 |=============================40%==|
Label 2 |=================30%==|
Label 3 |======15%==|
and so on. The bars display just fine, but how do I add the labels on the left ? This is the piece of script that displays the bars (given a div with id 'chart' and the proper css).
chart = d3.select('#chart')
.append('div').attr('class', 'chart')
.selectAll('div')
.data(data).enter()
.append('div')
.transition().ease('elastic')
.style('width', function(d) { return d + '%'; })
.text(function(d) { return d + '%'; });
You'll find a working example here . So, how do I add labels on the left of every bar so that the user knows what every bar represents ?
I think your idea of appending a <div> containing a label before each bar is reasonable. To do so, you first need to append a <div> for each bar, then append a <div> containing the label, and finally append a <div> containing the bars. I've updated your example with a JSFiddle here, with the Javascript code below (some changes were also required to the CSS):
// Add the div containing the whole chart
var chart = d3.select('#chart').append('div').attr('class', 'chart');
// Add one div per bar which will group together both labels and bars
var g = chart.selectAll('div')
.data([52,15,9,3,3,2,2,2,1,1]).enter()
.append('div')
// Add the labels
g.append("div")
.style("display", "inline")
.text(function(d, i){ return "Label" + i; });
// Add the bars
var bars = g.append("div")
.attr("class", "rect")
.text(function(d) { return d + '%'; });
// Execute the transition to show the bars
bars.transition()
.ease('elastic')
.style('width', function(d) { return d + '%'; })
Screenshot of JSFiddle output

Changing size of rect to fit inside text

I have some text I append to an svg object with D3.js using append('text').
My code looks like this:
var countries = svg.append("svg:g")
.attr("id", "countries");
var stateTexts = svg.append('rect')
.attr('x', xstateText)
.attr('y', ystateText)
.attr('width', 'auto')
.attr('height', 'auto')
var stateText = svg.append('text')
.attr('x', xstateText)
.attr('y', ystateText)
.style("font-family", "Arial")
.style("font-size", "14px")
.style("font-weight", 'bold');
What I'd like is to put that text "inside" a rect which changes size based on the length of the text I append. The rect would have a stroke of 1px so as to give the appearance of a box.
How can I accomplish this? Obviously, width and height can't be set to auto (css properties). I need something else there that can work native to D3.
Edit: Confused by the downvote..
You can't do this automatically in SVG -- the dimensions of the text have to be computed and the rectangle added accordingly. Fortunately, this is not too difficult. The basic idea is illustrated in this function:
function mkBox(g, text) {
var dim = text.node().getBBox();
g.insert("rect", "text")
.attr("x", dim.x)
.attr("y", dim.y)
.attr("width", dim.width)
.attr("height", dim.height);
}
Given a container and a text element, compute the dimensions of the text element (the text must be set for this to work correctly) and add a rect to the container with those dimensions. If you want to get a bit fancier, you could add another argument that allows you to specify padding so that the text and the border are not immediately next to each other.
Complete demo here.

Using d3.js to create an SVG at several divs

Suppose I have some HTML which looks like:
<html>
<body>
<div class = "a"></div>
...
<div class = "a"></div>
...
<div class = "a"></div>
...
</body>
<html>
where the ...'s are just paragraphs or other code.
Problem: I'd like to be able to use d3.js to append an SVG at each of these div's.
For example, let's say I want to make a rectangle like:
var svg = ((SOMETHING GOES HERE!))
.append("svg")
.attr("width", w)
.attr("height", h);
var sep = svg.selectAll("rect")
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("width", 100)
.attr("height", 10)
How can I use the selectors on the first line to do this? I've tried selectall() and select() with various "div.a", ".", etc., things, but nothing seems to work.
You can just append the SVG to your div with:
d3.selectAll("div.a").append("svg")
And if you want to select and act upon those SVGs after you made them just add a sub-select:
d3.selectAll("div.a").select("svg").append("rect").attr("height", 50).attr("width", 50)
Or you could class your SVGs and select them after you made them:
d3.selectAll("div.a").append("svg").attr("class", "divSVG")
d3.selectAll("svg.divSVG).append("rect").attr("height", 50).attr("width", 50)
Also, if you want them to appear before your elements, use insert instead of append:
d3.selectAll("div.a").insert("svg", "p")

Categories

Resources