I made a bubble chart and is working fine.But i need and even based feature in which i click on each circle and the data related to that circle will show in tabular form in another div..
<div id="bubblechart"></div>
<div id="table"></div>
first div contain the bubble chart and working fine. table div is used as container for the table generated.
here is my code.
var node = svg.selectAll(".node")
.data(bubble.nodes(classes(root))
.filter(function(d) { return !d.children; }))
.enter().append("g")
.attr("class", "node")
.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
node.append("circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) { return color(d.packageName); })
.on("mouseover", animateFirstStep)
.on("mouseout", animateSecondStep);
node.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.className; });
You can add an .on("click", clickFunction) to the node. This will work like your mouseover and mouseout lines.
In the clickFunction function, control the content of the target div using
document.getElementById('targetDiv').innerHTML = targetText;
or with jQuery
$("#targetDiv").html(targetText);
Related
I draw a graph from a set of nodes and links using the following update function with nodes and links arrays defined earlier in the code.
function update() {
var link = svg.selectAll(".link")
.data(links);
link.enter().insert("line")
.attr("class", "link");
var node = svg.selectAll(".node")
.data(nodes);
node.enter().append("svg:g")
.attr("class", "node")
.attr("id", function(d) { return d.name })
.on("dblclick", dblclick)
.on("mouseover", function(d) {drawTags(tags, d.name);})
.on("mouseout", function(d) {
d3.select("#"+d.name).selectAll(".tool")
.transition()
.delay(800)
.remove();
})
.call(force.drag);
node.append("circle")
.attr("class", "circle")
.attr("r", 40);
// display name in nodes if node structure
node.append("text")
.attr("text-anchor", "middle")
.attr("dy", ".35em")
.text(function(d) { return d.name; });
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("transform", function(d) {
return "translate(" + d.x + "," + d.y + ")";
});
});
force.start();
}
On dynamic update of the graph, after double click event on a node, I fetch additional nodes and links and display them. So far, I was able to append nodes and links to their corresponding arrays, hence update drawing. However, the update function would loop through all elements for the display.
Therefore I would like to pass newNodes and newEdges to the update function and only draw new elements. The issue is that new elements replace existing ones in the svg code rather than to be appended.
Is there a way to append new elements to previously existing ones in the drawing?
Full code is available on fiddle (https://jsfiddle.net/pducrot/4eyb81kx/) mouse over a node and click on any appearing tag to see what's happening.
Small problem on one viz.
I have a bar chart, and I want it to display some text in the line on 'mouseenter'. That works fine, but I want to remove this text on 'mouseout', and I can't seem to get the hang of it.
Thank you very much for your help!
Attached: the concerned section of the d3.js script
d3.selectAll("div.line")
.append("div")
.attr("class","bar")
.style("width", function(d){return d.occurrence /10 + "px"})
.on("mouseenter", function(d) {
d3.select(this)
.append("text")
.text(function(d){return d.occurrence + " occurences"});
})
.on("mouseout", function(d) {
d3.select(this)
.select(".text").remove();
});
In your code, you're trying to select .text on mouseout. You're selecting nodes with which have the class: "text" rather than text nodes. Remove the dot.
I'd probably also change the mouseout "select" to "selectall" just in case you miss a mouseout event and accidentally add two text nodes.
Edit:
http://jsfiddle.net/QbGRE/
d3.select("div.line").selectAll("div.bar")
.data(data, function(d) { return d.id; })
.enter()
.append("div").attr("class","bar")
.style("width", function(d){return d.occurrence /10 + "px";})
.on("mouseover", function(d) {
d3.select(this)
.append("text").style("pointer-events", "none")
.text(function(d){return d.occurrence + " occurences";});
})
.on("mouseout", function(d) {
d3.select(this)
.select("text").remove();
});
Cleaned up your code.
"mouseover/mouseout" instead of "mouseenter/mouseout"
.select("text") instead of ".text".
style("pointer-events", "none) on the text to stop it causing extra mouse events when it's added.
Added fake data.
The easiest way to do this is to assign a unique ID to the new text element and select by that:
.on("mouseenter", function(d) {
d3.select(this)
.append("text")
.attr("id", "myText")
.text(function(d){return d.occurrence + " occurences"});
})
.on("mouseout", function(d) {
d3.select("#myText").remove();
});
I'm using a range slider to add/remove points from a line which follows an histogram.
Without updating the data, the text labels are shown correctly, when I update the values with the slider I'd like that the text-labels follow the line, so they show the values of the points correctly.
The update for the line works, but I am not able to update the text labels correctly.
Right now the laberls are plotted like so outside of the on-change function:
var SerifText = svg.append("g")
.attr("id", "serif-labels")
.selectAll("text")
.data(histogSerif)
.enter()
.append("text")
.text(function (d) { return d.y >= 1 ? d.y : null; })
.attr("text-anchor", "middle")
.attr("font-size", 10 + "px")
.attr("fill", "#f0027f")
.attr("x", function (d) { return x(d.x)})
.attr("y", function (d) { return y(d.y) - padding; })
.attr("visibility", "hidden"); //the hidden & visible is managed by an external checkbox
And then on the on-change function I put this code:
SerifText.selectAll("text").remove();
/* If I do SerifText.remove() it does remove the text but also the group of course,
but as it is it doesn't work */
SerifText.selectAll("text")
.data(histogSerif)
.enter()
.append("text")
.text(function (d) { return d.y >= 1 ? d.y : null; })
.attr("text-anchor", "middle")
.attr("font-size", 10 + "px")
.attr("fill", "#f0027f")
.attr("x", function (d) { return x(d.x)})
.attr("y", function (d) { return y(d.y) - padding; });
But this doesn't work unfortunately. I'd like also to be able to retain the manage of the visible/hidden status by the external checkbox if possible.
Full code is here
Instead of trying to save a reference to the labels that you are going to delete, and then re-selecting them, how about just use a variable that references the SerifText element selection, e.g.:
var SerifTextGroup = svg.append("g")
.attr("id", "serif-labels");
SerifTextGroup.selectAll("text")
.data(histogSerif)
.enter()
//... and so on
Then the rest of your code should work as written (just change SerifText to SerifTextGroup).
I'm relatively new to D3 and trying to add labels to a bar chart.. I keep running into the problem of labels applying all values to each label. Precedding this code is normal data load etc.
// Controls Bar Layout and Offset (x(d.weekOf)+20)
var property = svg.selectAll(".property")
.data(data)
.enter().append("g")
.attr("class", "g")
.attr("transform", function(d) { return "translate(" + (x(d.weekOf)+20) + ",0)"; });
// Theese are the bars, width is the width of the bars
property.selectAll("rect")
.data(function(d) { return d.emissions; })
.enter().append("rect")
.attr("width", "80")
.attr("y", function(d) { return y(d.y1); })
.attr("height", function(d) { return y(d.y0) - y(d.y1); })
.attr("opacity", "0.7")
.style("fill", function(d) { return color(d.name); });
// Add Capacity Labels
property.selectAll("text")
.data(data)
.enter()
.append("text")
.text(function(d, i) {return d.Internal; })
.attr("x", 41)
.attr("y", 210)
.attr("text-anchor", "middle");
Clearly I'm missing something simple..?
Your labels are a subselection of the property selection, so instead of using data() to join each property label to the entire dataset as you are, you should instead use data to join to the corresponding parent datum, like so:
property.selectAll("text")
.data(function(d) {return [d];})
.enter()
.append("text")
.text(function(d, i) {return d.Internal; })
.attr("x", 41)
.attr("y", 210)
.attr("text-anchor", "middle");
I am using d3.js for bubble chart.its working fine but i need to write custom tool tip for the data which i am showing.currently i just appended one title tag so it just showing one data with tooltip
what if i have more data to show and want to show in form of a table.
Here is my code.
d3.json("data/bubble.json", function(error, root) {
var node = svg.selectAll(".node")
.data(bubble.nodes(classes(root))
.filter(function(d) { return !d.children; }))
.enter().append("g")
.attr("class", "node")
.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 d.r; })
.style("fill", function(d) { return color(d.packageName); });
node.append("text")
.attr("dy", ".3em")
.style("text-anchor", "middle")
.text(function(d) { return d.className.substring(0, d.r / 3); });
});