I have the following code to append a line on an SVG canvas. I am able to get the scope run when I double click on the path as the alert box pops up but the line itself doesn't gets removed. Where am I going wrong? Am I using this incorrectly?
var lineFunction = d3.svg.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.interpolate("step");
lineGraph = layer.append("path")
.attr("d", lineFunction(lineData))
.attr("stroke", "black")
.attr("stroke-width", 1)
.attr("fill", "none")
.attr("id","aggregation")
.attr("data", "newline")
.style('marker-end', "url(#end-arrow)")
.on("dblclick",function(d){
alert("double");
d3.this.remove();
});
The method .remove() needs to be called on a D3 selection. In an event handler you can obtain the selection containing the element which was target of the event by doing
d3.select(this)
Thus, changing your handler to
.on("dblclick",function(d){
d3.select(this).remove();
});
should do the trick.
Related
I have two d3 visualizations, and when I click on a link on the sankey diagram (defined by an email), I want to change the radius of the corresponding node (with the same email) on the force directed network graph. No matter what I try or search on the internet I cannot find a way to adjust the attribute of one individual node without selecting all the circles.
var link = svg.append("g").selectAll(".link")
.data(graph.links)
.enter().append("path")
.attr("class", "link")
.on("click", function (d,i){
svg2.selectAll("circle").each(function (f,i){
if (f.id == d.email)
{
//CHANGE RADIUS OF F or color or anything
//svg2.select(f).attr("r",10); DOESNT WORK
//f.attr("r",10) DOESNT WORK
}
});
})
.attr("d", path)
.style("stroke-width", function(d)
{ return Math.max(0.2, d.dy); })
.sort(function(a, b) { return b.dy - a.dy; });
I have a d3.js line chart which may have negative values. My Y-span starts at 0 and goes up to the maximum value in the dataset. Thus, the line goes underneath the X-axis when there is a negative value.
This is fine, but what I need is to just hide the part of the line that is underneath the X-axis. I want to keep the values as they are, just use some CSS or JS to make the part of the line underneath the X-axis invisible.
I have tried with various overflow settings, but it doesn't seem to help. It is possible to make everything below the X-axis invisible by placing an element over that part, but then the X-axis labels are hidden too.
This is the code drawing the line:
x.domain([d3.min(data, function(d) { return d.date}), d3.max(data, function(d) { return d.date})]);
y.domain([0, 1.05 * d3.max(data, function (d) { return d.value; })]);
area.y0(y(0));
g.append("path")
.datum(data)
.attr("fill", "#f6f6f6")
.attr("d", area);
//create line
var valueline = d3.line()
.x(function (d) { return x(d.date); })
.y(function (d) { return y(d.value); });
g.append("path")
.data([data])
.attr('fill', 'none')
.attr('stroke', '#068d46')
.attr("class", "line")
.attr("d", valueline);
Fiddle: https://jsfiddle.net/c1bvrd50/1/
One way to solve this problem is to clip the line inside a rectangle covering the positive values area. In SVG, this is done with clip-path.
This happens in two steps:
Define a rect inside clipPath, covering the chart area only:
g.append('clipPath')
.attr('id', 'clipRect')
.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', width)
.attr('height', height)
Clip the line path, using clip-path attribute:
g.append("path")
.data([data])
/* ... */
.attr("d", valueline)
.attr('clip-path', 'url("#clipRect")')
Updated jsFiddle implementing the solution: here.
What is left to do is update the tooltip's mousemove event listener in order not to display the tooltip whenever the value is lower than 0.
Recommendation as P.S.: Whatever the use case of the chart is, it is most likely desirable to show the portions of the chart with negative values. Therefore, the chart's y axis should cover values lower than 0, rather than omitting these.
I am looking at the Bubble Chart by Mike Bostock: http://bl.ocks.org/mbostock/4063530 that uses circle packing. I would like to however, be able to color the circles by the name of the containing class.
I am trying it in JSBin here: http://jsbin.com/qoveguvopu/edit?css,js,output
My fault is here:
node.append("circle")
.attr("r", function(d) { return d.r; })
.style("fill", function(d) {return color(d.data.name);});
Thanks!
Kind of like this:
You can get the data bound to the parent...
d.parent.data.name
... and color the circles according to it, first checking if a parent exists:
node.append("circle")
.attr("r", function(d) {
return d.r;
})
.style("fill", function(d) {
if (d.parent) {
return color(d.parent.data.name)
};
});
Here is your updated Bin: http://jsbin.com/ruyegidopo/1/edit
In the following d3.js code:
svg.selectAll(".bar")
.data(data)
.enter()
.append("rect")
.attr("transform", "translate(10,0)")
.attr("class", "bar")
.attr("x", function(d) { return x(d.thread_id); })
.attr("width", x.rangeBand())
.attr("y", function(d) { return y(+d.traffic); })
.attr("height", function(d) { return height - y(+d.traffic); })
.on('mouseover', tip.show) // First time call to show a tooltip
.on('mouseover', justChecking) // Second time to call a Function
.on('mouseout', tip.hide);
When I execute this code, only the second function output is shown but the tooltip disappears.
I want to call both of them on mouseover, i.e., call the function as well as show the tooltip. Any ideas are appreciated?
Any event handler you attach overwrites previously attached event handlers. You can however call both of your functions in the same handler:
.on('mouseover', function(d, i) {
tip.show(d, i);
justChecking(d, i);
})
I'm working on building a molecule creator in D3 using the original example created by Mike Bostock: http://bl.ocks.org/mbostock/3037015
I'm using a force layout just like in the example. My problem is when I add a new Node/atom dynamically, it doesn't move with the rest of the graph. I've read other questions and implemented everything that is suggested and have made sure that I'm following the proper update/join procedure that D3 requires and yet still the added carbon refuses to move with the rest of the graph.
Here is my update/create function:
function buildMolecule () {
// Update link data
link = link.data(links);
// Create new links
link.enter().append("g")
.attr("class", "link")
.each(function(d) {
d3.select(this)
.insert("line", ".node")
.style("stroke-width", function(d) { return (d.bond * 2 - 1) * 2 + "px"; });
d3.select(this)
.filter(function(d) { return d.bond > 1; }).append("line")
.attr("class", "separator");
d3.select(this)
.on("click", bondClicked);
});
// Delete removed links
link.exit().remove();
// Update node data
node = node.data(nodes);
// Create new nodes
node.enter().append("g")
.attr("class", "node")
.on("click", atomClicked)
.each(function(d) {
console.log('d:', d);
// Add node circle
d3.select(this)
.append("circle")
.attr("r", function(d) { return radius(d.size); })
.style("fill", function(d) { return color(d.atom); });
// Add atom symbol
d3.select(this)
.append("text")
.attr("dy", ".35em")
.attr("text-anchor", "middle")
.text(function(d) { return d.atom; });
d3.select(this).call(force.drag);
});
// Delete removed nodes
node.exit().remove();
force.start();
}
JsFiddle: http://jsfiddle.net/2dPMF/1/
Any help would be greatly appreciated!
You're modifying the data structures of the nodes and links beyond adding and deleting nodes, which messes up the force layout. I'm talking about these lines in particular.
function bigBang () {
links = links.concat(linksList);
nodes = nodes.concat(nodesList);
buildMolecule();
}
The first two lines in that function are what I'm talking about. Working jsfiddle here.