animate this element in d3js - javascript

Ok so I have the following code example where I have circles in an svg element. Each circle has a click event and I'm trying to animate the circle that was clicked. Currently all circles animate because I'm referring to the bubble object. What I want is to refer to the clicked object its self and not the other ones:
var data_items=[100,200,300];
var svg = d3.select("#chart")
.append("svg").attr("width", 800).attr("height", 600);
var g = svg.selectAll(".bubbleContainer")
.data(data_items)
.enter().append("g")
.attr("class","bubbleContainer");
var bubble = g.append("circle")
.attr("class","bubble")
.attr("cx", function(d) {
return d;
})
.attr("cy", function(d) {
return d
})
.attr("r", function(d) {
return d/2
})
.on("click",function(d){
bubble
.transition()
.duration(1000)
.attr("r",1000)
})
Any help is much appreciated
Thanks!

What Lars Kotthoff wrote would work. Alternatively – and I'm not sure which is more idiomatic:
Inside the click handler, the this context refers to the clicked DOM element.
So the following would do it too:
.on("click",function(d){
d3.select(this)
.transition()
.duration(1000)
.attr("r",1000)
});

You can use d3.event.target to access the element that is being clicked in the event handler. See for example this jsfiddle.

Related

D3 - how to fire an on-click function for only a specific group of nodes

In this d3 force layout viz project I'm trying to remove the user's ability to click on the bigger yellow nodes. I have an on-click, fire the clicknodeControl function,
nodes.append('circle')
.attr("r", 28)
.attr("id", "hoverdots")
.style("opacity", 0)
.style("fill", "#00bedd")
.on("click", function(d) { return clicknodeControl(d.group); })
.style("z-index", "10")
.on("mouseover", mouseover)
.on("mouseout", mouseout)
and then ideally this variable would pass through the clicknode function to one group of nodes but not the other:
var clicknodeControl = d3.scaleOrdinal([`clicknode`, ``]);
This does not seem to be working in practice, the clicknode function is not being passed through.
Thanks if anyone has any ideas on this!!
In D3 V7 mouse event handlers have event as the first argument and datum as the second.
Replace
.on("click", function(d) { return clicknodeControl(d.group); })
with:
.on("click", (_, d) => clicknodeControl(d.group))

div element is getting appended outside the body

I want to implement a list on right-click of a data node. In order to do so I came across d3-context-menu plugin of d3.js. The problem I am facing is that the div element is getting appened outside the body tag.
I have never seen such an issue before.
I am following the plugin example given here:
http://plnkr.co/edit/hAx36JQhb0RsvVn7TomS?p=preview
This is the link to the library documentation:
https://github.com/patorjk/d3-context-menu
I have no clue why it is behaving in such manner. My code structure looks like this :
eventGroup = focusClip.selectAll(".event").data(data);
// Enter phase ---
eventGroupEnter = eventGroup.enter().append("svg");
eventGroupEnter.append("rect");
eventGroupEnter.append("circle");
eventGroupEnter.append("text");
// Event Group
eventGroup
.attr("class", "event")
.attr("x", function(d) {
return parseInt(x(d.time)) - 10;
}) // offset for the bg and center of dot
.attr("y", function(d) {
return parseInt(y(d.plotY));
})
.attr("width", function(d) {
return parseInt((d.label.length / 2)) + 60 + "em";
})
.attr("height", "20");
// Background
eventGroup.select("rect")
.attr("x", 0) // removes the "<rect> attribute x: Expected length, 'NaN'" Error
.attr("y", 4)
.attr("width", "100%")
.attr("height", "12")
.attr("fill", "url(#event-bg)");
menu = [{
title: "Item #1"
}];
// Dot
eventGroup.select("circle")
.attr("class", "dot")
.attr("r", 4)
.attr("cx", 10)
.attr("cy", 10)
.attr("fill", function(d) {
return d.evtColor ? d.evtColor : "#229ae5";
})
.attr("stroke", function(d) {
return d.evtColor ? d.evtColor : "#229ae5";
})
.attr("stroke-width", 2)
.on("contextmenu", d3.contextMenu(menu, function() {
console.log("Quick! Before the menu appears!");
}))
.on("mouseenter", tooltip.mouseover)
.on("mouseleave", tooltip.mouseout)
.on("click", annotateBox.click);
In order to explain it well I am adding the image of the chart:
The right click event is being called on the "dot" part of the event. Why would div element get appended outside the body?
This seems to be by design. If you look at the source code of that plugin, you'll see:
d3.selectAll('.d3-context-menu').data([1])
.enter()
.append('div')
.attr('class', 'd3-context-menu');
Since selectAll is called on the root, the div will be appended to the <html>, not to the <body>.
So, the author either did this intentionally or she/he forgot that d3.selectAll is different from selection.selectAll.
Here is a basic demo, click "Run code snippet", open your browser's dev tools and inspect the snippet window.
d3.selectAll("foo")
.data([1])
.enter()
.append("div")
.attr("class", "test")
<script src="https://d3js.org/d3.v3.min.js"></script>
You're gonna see this:
<html>
<head>...</head>
<body>...</body>
<div class="test"></div>
</html>

D3.js transition for set of rectangles

Here is my problem, I want to use transition() method of d3.js but for a set of rectangles that I don't know the size.
For example: At first I have 2 rectangles then 3 then 4 and then 2.
Can I use transition() in this case? If so, what's the best way to do it?
Thanks in advance
I use invisible rectangles for providing good hover effect in charts. So while creating the rectangles I simply assign them a class. While updating I remove elements of that class first and just repeat the process.
tmpsvg = svg.transition();
g = tmpsvg.select('g');//prefer to refer by classname
g.selectAll(".bar-rect").remove();
var rect = g.selectAll(".bar-rect")
.data(data)
.enter().append("svg:rect")
.attr("class", "bar-rect")
.attr("x", function(d, i) { return x(d.key)-10; })
.attr("y", 0)
.attr("width", "20px")
.attr("height", h)
.on("mouseenter", function(d, i) {
//TOOLTIP EFFECTS ON MOUSE-ENTER
$('#myls'+i).animate( {opacity:1 },100);
$('.chart-tooltip[data-index='+i+']').addClass('hover');
// Add hover class to the targeted point
}).on("mouseleave", function(d, i) {
//REMOVE TOOLTIP EFFECT ON MOUSE-LEAVE
$('#myls'+i).animate( {opacity:0 },100);
$('.chart-tooltip').removeClass('hover');
// Remove hover class from the targeted point
});
This may not be the most efficient way but hope it helps.

mouse over event line path d3

I created a multi line graph by d3.
I'm trying to create a handler for each line (path) but it doesn't work.
Here is the code creating the path:
var line2 = d3.svg.line()
.x(function(d, i){return x(AXValues[i])})
.y(function(d, i){return y(AYValues[i])});
p2 = svg.append("path")
.datum(ArticleData)
.transition()
.delay(1100)
.attr("id", "p"+i)
.attr("class", "p"+i)
.attr("d", line2(AXValues, AYValues))
.style("stroke", "Brown")
.style("stroke-width", 2)
.style("fill", "none");
Im trying to do something like this:
.on("mouseover", this.style("stroke-width", 5));
You'll need to attach the listener to the appended object:
p2.on("mouseover", function () {
d3.select(this).style("stroke-width", 5);
});
Thanks to #Lars Kotthoff for the correction
You can do this through css with the 'hover' event, for instance for the p2 class you are applying you can have some css that looks like this.
p2:hover {
stroke-width: 5;
}
hovering over would change the stroke-width to 5, and once the hover event is over the element will go back to its original stroke-width

Displaying text over a node in a d3 force-layout graph

I am creating a force-layout graph using d3 and I am trying to make the name of a specific node appear when I mouse over that node. I know how to add the text before any mouse over effect and thought that I could just move that part of the code into the mouseover function but that did not work. I will also need to make the text disappear when I move the mouse off of the node. Here is the mouseover function where I attempt to add the name to the node:
function mouseover() {
d3.select(this).transition()
.duration(750)
.attr("r", function(d) {return d.size + 10;});
var labels = gnodes.append("text")
.text(function(d) { return d.name;})
console.log(labels);
}
Here is a link to a fiddle of the complete code as well:
http://jsfiddle.net/ohiobucks23/QvVU6/
If not using a tooltip per good recommendation by Bhatt, you will need to:
1) declare gnodes outside the drawGraph() function so that it is visible to the mouse functions, and
2) make the following changes to the mouse functions:
function mouseover(d) {
d3.select(this).transition()
.duration(750)
.attr("r", function (d) {return d.size + 10;});
// locate node and append text; add class to facilitate subsequent deletion
gnodes.filter(function (o) {return o.index === d.index;})
.append("text")
.attr("class", "nodetext")
.text(d.name);
}
function mouseout(d) {
d3.select(this).transition()
.duration(750)
.attr("r", function (d) {return d.size;});
// delete text based on class
d3.selectAll(".nodetext").remove();
}
Here is the complete FIDDLE. I changed the text of the root node element so that you can see that the mouseover function is really acting on the selected node.

Categories

Resources