I'm using D3.js for my personal project.
But, I faced with some troubles.
bubble.nodes(root)
svg = d3.select("svg").attr("class", "bubble")
var node = svg.selectAll(".node")
.data(bubble.nodes(root)
.filter(function(d) {
return !d.children;
}))
.enter()
.append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
})
In the picture, I want to get "r" value in the circle.
How can I get this value?
Also, this circle is one part of bubble chart node.
Using vanilla JS... getElementsByTagName('circle'), then getAttribute('r') to find the value of r
let circle = document.getElementsByTagName('circle');
let target = circle[0].getAttribute('r');
console.log(target);
<circle r="0.75847397430597"></circle>
Related
I am trying to make modifications to the D3 sankey example here:
http://bl.ocks.org/d3noob/c2637e28b79fb3bfea13
I want to shift the y-position of each node to a specified location (300px in the example below).
The most straight forward way I can to see to achieve this is to simply repurpose dragmove() to be called after the the SVG elements have been added. I've made changes to d.y in this function to shift to 300px:
function dragmove(d) {
d3.select(this).attr("transform",
"translate(" + d.x + "," + (
d.y = 300
) + ")");
sankey.relayout();
link.attr("d", path);
}
This function is called when adding the nodes:
var node = svg.append("g").selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; })
.call(d3.behavior.drag()
.origin(function(d) { return d; })
.on("dragstart", function() {
this.parentNode.appendChild(this); })
.on("drag", dragmove));
At present, it shifts to 300px as expected on the specified mouse event, but I want it to shift on its own after all the SVG elements have been added instead.
Simply using .call() without the mouse event doesn't work.
I've also tried to incorporate the shift in var node instead:
return "translate(" + d.x + "," + 300 + ")"; })
However this leads to a mismatch between the leads and the nodes, and calling sankey.relayout() doesn't seem to make a difference.
Found a solution.
First I removed .call() at the end of var node, as I don't need the drag event:
var node = svg.append("g").selectAll(".node")
.data(graph.nodes)
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")"; });
Then I set d.y to the arbitrary location (300):
return "translate(" + d.x + "," + (d.y = 300) + ")"; });
Finally I forced it to re-draw the connecting links immediately after var node.
sankey.relayout();
link.attr("d", path);
I've got this linechart, on each value in the chart I am placing a dot.
when hovering over the dot I would like to show the value using a d3-tip tooltip.
Here is what I got so far:
var svg = chart.append("svg")
.attr("width", outerWidth)
.attr("height", outerHeight)
.append("g")
.attr("transform", "translate(0,10)");
newData.graphSeries.forEach(function (current, index, all) {
//current = this exact part of the array
//index = the array index nr [0][1][2] etc
//all = the complete array
var graph = current.Values,
color = current.Color;
var nextLine = d3.svg.line()
.interpolate(current.Interpolate)
.x(function (d) {
return x(d.x);
})
.y(function (d) {
return y(d.y);
});
svg.append("path")
.datum(graph)
.attr("transform", "translate(" + yAxisWidth + ",0)")
.attr("class", "line stroke-" + color)
.attr("d", nextLine);
//Placing tooltips
if (current.Tooltips == true) {
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.html(function(d) {
return "<strong> TEST: " + newData.y.Unit + "</strong><span>" + d.x + "</span>"
});
//create circles to place the tooltip on
svg.selectAll('dot')
.data(graph)
.enter().append("circle")
.attr("r", 3,5)
.attr("style", "cursor: pointer")
.attr("class", "circle-" + color)
.attr("transform", "translate(" + yAxisWidth + ",0)")
.attr("cx", function(d) { return x(d.x) })
.attr("cy", function(d) { return y(d.y) })
.on('mouseover', tip.show )
.on('mouseout', tip.hide);
svg.call(tip);
}
});
I checked if d3-tip exists in the code and it does.
I can console.log the tip variable, also the dots are showing and even the mouseover and mouseout are working correctly.
Still somehow tip.show doesn't seem to work.
I thought maybe it would show somewhere else in the document, but can't see it anywhere.
Could you please help out.
Best,
Bart
The problem was actually easier to solve then expected.
The tooltip might be 'pushed' away by all other html code.
Adding .style('z-index', '99999999999'); will help to get that straight.
See:
var tip = d3.tip()
.attr('class', 'd3-tip')
.offset([-10, 0])
.style('z-index', '99999999')
.html(function(d) {
return "<strong> TEST: " + newData.y.Unit + "</strong><span>" + d.x + "</span>"
});
I am trying to use the bubble chart example as a template to build a visualisation. I have my JSON as a flat-hierarchy, such that there is one element called children and that holds an array of objects that I want to visualise.
The JSON looks like this:
{
"children":[
{
"acc":"Q15019",
"uid":"SEPT2_HUMAN",
"sym":"SEPT2",
"name":"Septin-2",
"alt_ids":"",
"ratio":0.5494271087884398,
"pval":0.990804718
},
...,
{
"acc":"Q16181",
"uid":"SEPT7_HUMAN",
"sym":"SEPT7",
"name":"Septin-7",
"alt_ids":"",
"ratio":1.1949912048567823,
"pval":0.511011887
}
]
}
I have modified the example code as follows:
var diameter = 960,
format = d3.format(",d"),
color = d3.scale.quantile().range(colorbrewer.RdBu[9]);
var bubble = d3.layout.pack()
.sort(null)
.size([diameter, diameter])
.padding(1.5);
var svg = d3.select("body").append("svg")
.attr("width", diameter)
.attr("height", diameter)
.attr("class", "bubble");
d3.json("datagraph.json", function(datagraph) {
var node = svg.selectAll(".node")
.data(bubble.nodes(datagraph))
.enter().append("g")
.attr("class", "node")
.attr("id", function(d) { return d.acc; })
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
//node.append("title").text(function(d) { return d.className + ": " + format(d.value); });
node.append("circle")
.attr("r", function(d) { return 30; })
.style("fill", function(d) {
if(d.ratio == null)
return "#ffffff";
else
return color(d.ratio);
});
node.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.acc; });
});
The resultant HTML has a ton of <g> tags responding to each element except they are never translated to the right position, but instead sort of sit on top of each other on the top left corner. By investigating in Firebug, I figured this happens presumably because the pack() algorithm does not get the objects one at a time, but the whole array as a single element, thus individual elements don't get .x and .y values.
If I change the .nodes() argument to datagraph.children I get the elements one at a time in nodes() iteration, but oddly enough I get a single <g> object. Since I don't need to flatten a hierarchy I skipped the classes(root) function, in the example. What I am wondering is whether or not the packageName attribute plays any role in the nodes()?
How can I resolve this issue?
You haven't specified a value accessor:
var bubble = d3.layout.pack()
.sort(null)
.size([diameter, diameter])
.padding(1.5)
.value(function(d) { return d.pval; }) //<- must return a number
Example here.
var nodeEnter = node.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
.on("click", click)
.on("mouseover",function (d){
if(d.name=="Purchased"){
jQuery.getJSON("RequestHandler?usercommand=jsoncompany&subcommand=propCount&useraction=d3Tree_frm&mgmtId="+d.id+"&type="+d.name, function(json){
var count=JSON.stringify(json.prop_purchased_count);
result="Purchased Property :"+count;
});
}
var g = d3.select(this);
var info = g.append("text")
.classed('info', true)
.attr('x', 30)
.attr('y', 30)
.text(result); //result="Amount":200\n"Amount":300\n"Amount":400
})
.on("mouseout", function() {
d3.select(this).select('text.info').remove();
});
//result="Amount":200\n"Amount":300\n"Amount":400
i want to display tooltip such that after \n it appears in a new line within that tooltip.
How to achieve it ?
Thanks in advance
I can see result being set in the code you posted, however what we cannot see is where result is being set to get the content you are 'saying' it contains. That way we could help you interpret the application of these proven recommendations a lot better. But in anycase, have a look at these resources to help you in your quest.
http://bl.ocks.org/mbostock/7555321
How to dynamically display a multiline text in D3.js?
In the else part add "Amount:"+ count + "\n" while you are concatenating the newline
I am currently using the d3.layout.tree() to compute the positions of my data.
var tree = d3.layout.tree()
.sort(null)
.size([size.height, size.width - maxLabelLength * options.fontSize])
.children(function(d)
{
return (!d.contents || d.contents.length === 0) ? null : d.contents;
});
Initially I compute and add my nodes like this:
var nodes = tree.nodes(treeData);
var nodeGroup = layoutRoot.selectAll("g.node")
.data(nodes, function (d) { return d.name })
.enter()
.append("svg:g")
.attr("class", "node")
.attr("transform", function(d)
{
return "translate(" + d.y + "," + d.x + ")";
});
nodeGroup.append("svg:circle")
.attr("class", "node-dot")
.attr("r", options.nodeRadius);
Now I add a new node to the treeData and also to the layoutRoot:
var grp = layoutRoot.selectAll("g.node")
.data(nodes, function (d) { return d.name })
.enter()
.append('svg:g')
.attr("transform", function (d)
{
return "translate(" + d.y + "," + d.x + ")";
})
grp.append("svg:circle")
.attr("class", "node-dot")
.attr("r", options.nodeRadius)
The problem is now, that the newly computed nodes that are already present in the rootLayout have different x,y coordinates after having added a new node. But they are not within the enter() or exit() selection and are thus not redrawn at their correct position. How is this supposed to be handled, ie. how should the position of the nodes that have not changed anything but their coordinates be updated/refreshed?
I a noob to d3js. So don't be too harsh :D
I would separate the enter() selection from the update of nodes like this :
var nodeGroup = layoutRoot.selectAll("g.node")
.data(nodes, function (d) { return d.name });
// Enter selection
nodeGroup.enter()
.append("svg:g")
.attr("class", "node")
// Update
nodeGroup.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});
var nodeDots = layoutRoot.selectAll("g.node-dot")
.data(nodes, function (d) { return d.name });
// Enter
nodeDots.enter()
.append("circle")
.attr("class", "node-dot")
// Update
nodeDots.attr("r", options.nodeRadius);
Hope this helps, but in a general way of speaking, it is perhaps easier to code this way, with separation of enter and updates (see here for more info)