Using D3 transitions disables hover CSS on SVG - javascript

I have some circles that I want to change fill when I hover over them. I give them "pins" class and here's the CSS for them:
.pin {
fill: #9ecae1;
stroke:#3182bd;
}
.pin:hover{
fill:steelblue;
}
Each pin has a value and I want to include some transition so that if there is a change in that value, the circles will momentarily flash some other color, green for instance. They work fine without the update. After the update, the hover no longer works.
Here is my code for the transition:
d[2] is just some key name.
svg.selectAll("circle").data(points, function(d) {return d[2];})
.transition()
.duration(500)
.style("fill", "green")
.attr("r", function(d) {return 5 + 10*Math.ceil(radius(d[3]));})
.each("end", function(d){
d3.select(this).transition()
.style("fill", "#9ecae1");
});
I was able to pinpoint that setting style("fill", xxx) disables the hover but why? And is there a way to get the momentary transition while still maintaining the hover?

I understood the problem, that is in the below code
svg.selectAll("circle").data(points, function(d) {return d[2];})
.transition()
.duration(500)
.style("fill", "green")
.attr("r", function(d) {return 5 + 10*Math.ceil(radius(d[3]));})
.each("end", function(d){
d3.select(this).transition()
.style("fill", "#9ecae1");
});
we are applying the color by using inline style, this inline is more priority than external css, So don't apply the color by using inline style instead use the attribute(fill) to fill the color, the line of code we have to change is remove .style("fill", "green") and replace it with attr("fill", "green")
and .style("fill", "#9ecae1") with .attr("fill", "#9ecae1")
Below is the modified code
svg.selectAll("circle").data(points, function(d) {return d[2];})
.transition()
.duration(500)
.attr("fill", "green")
.attr("r", function(d) {return 5 + 10*Math.ceil(radius(d[3]));})
.each("end", function(d){
d3.select(this).transition()
.attr("fill", "#9ecae1");
});
:)

Related

Highlighting circles by mouseover that have duplicate names

I have a search box that highlights all circles when they have the same name and fades out the circles that don't match. All working as expected.
<input class="highlight" name="searchbox" id="searchbox" type="text" list="initname-datalist" placeholder="Search Project/Initiative.." onInput="initiativeSearch(this.value)">
<datalist id="initname-datalist"></datalist>
function initiativeSearch(initSelection) {
circles.transition()
.delay(0)
.duration(500)
.style("opacity", function(d) {
return d.data.initiative_name !== initSelection ? 0.5 : 1;
})
.style("stroke", function(d) {
return d.data.initiative_name === initSelection ? "black" : "grey";
});
}
initiative_name is a column name in my CSV. I want to do a similar thing but using mouseover, so when a user mouseover a circle all other circles with the same name will be highlighted.
I have a current mouseover in place that adds a yellow stroke to the circle being moused over and also a tool tip. I don't necessarily need to retain the yellow stroke.
.on("mouseover", function(d) {
d3.select(this) // highlight the circle that the tooltip relates to
.transition()
.delay(0)
.duration(100)
.style("stroke", "yellow")
.style("stroke-width", 5);
tooltip.transition()
.duration(200)
.style("opacity", .95);
tooltip.html("<strong>" + d.data.initiative_name + "</strong>)
.style("left", d3.select(this).attr("cx") + "px")
.style("top", d3.select(this).attr("cy") + "px");
})
.on("mouseout", function(d) {
d3.select(this)
.transition()
.delay(0)
.duration(500)
.style("stroke", "grey")
.style("stroke-width", 1);
tooltip.transition()
.duration(500)
.style("opacity", 0);
});
Any ideas how I can highlight all circles with the same initiative_name using mouseover?
It's hard to write a solution without actually testing it with the data, but this is a possible one:
.on("mouseover", function(d) {
circles.style("opacity", function(e) {
return d.data.initiative_name !== e.data.initiative_name ? 0.5 : 1;
});
//etc...
Call initiativeSearch() on mouseover like this
.on("mouseover", function(d) {
initiativeSearch(d.data.initiative_name);
}

Adding OnClick event to D3 force layout graph

I am trying to add an OnClick event to the nodes of my force layout graph but when I try to click on them, nothing happens. I believe that it is because I am not using an svg element and the .on("click", click) only works with svg elements I think but I am not entirely sure. Here is the code that I am trying to implement:
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("circle")
.attr("r",function(d) {return d.size})
.style("fill",function(d) {return color(d.type);})
.on("click", click)
.call(force.drag);
node.append("title")
.text(function(d){return d.name;});
force.on("tick", function(){
node.attr("cx", function(d){return d.x;})
.attr("cy", function(d) {return d.y;});
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;});
});
function click() {
d3.select(this).select("circle").transition()
.duration(750)
.attr("r", 30)
.style("fill", "lightsteelblue");
}
When I try and click on a node, nothing happens. I am not sure what to do. I think the problem has to do with the:
.enter().append("circle")
I think it needs to be an svg element like ("g") or ("svg") but I couldn't figure that out. Any advice or suggestions would be appreciated. Thanks!
You have an extra .select("circle") in click(). Instead, it should start with just:
function click(){
d3.select(this).transition()...
}

Undefined is not a function - JAVASCRIPT - D3

Hi i have a donut pie chart and I want to make it grow when the page loads.
It was a normal donut chart that when i clicked on one of the element it would show it's info.
I added the growing part and it is working but my mouseclick part (that was working before the grow part) stopped working.
It says that "undefined is not a function" on the .on("mouseup", function(d, i) line.
So it works with the transition, it works with the mouseup but it's not working with both.
renderarcs.append('path')
.attr('d',arc)
.attr("fill", function(d, i) { return color(i); })
.transition()
.duration(2000)
.attrTween("d", tweenPie)
.on("mouseup", function(d, i){
$("#mostra-nome-banda").html(arrayBandas[i]['name']);
$("#pag-banda-plays").html(arrayBandas[i]['playcount']+" plays");
linkArtista= arrayBandas[i]['url']
d3.selectAll('path').transition()
.duration(100)
.attr("d", arc)
d3.select(this).transition()
.duration(100)
.attr("d", arcOver);
});
You need to add the handler before the transition:
renderarcs.append('path')
.attr('d',arc)
.attr("fill", function(d, i) { return color(i); })
.on("mouseup", function(d, i){
$("#mostra-nome-banda").html(arrayBandas[i]['name']);
$("#pag-banda-plays").html(arrayBandas[i]['playcount']+" plays");
linkArtista= arrayBandas[i]['url']
d3.selectAll('path').transition()
.duration(100)
.attr("d", arc)
d3.select(this).transition()
.duration(100)
.attr("d", arcOver);
})
.transition()
.duration(2000)
.attrTween("d", tweenPie);
Otherwise, you're attaching an event handler to the transition and not the selection. Transitions don't have mouseup events.

d3.js change color and size on line graph dot on mouseover

I made a line graph with d3.js (see the attached image1).
I managed to insert tooltips on graph dots when mouseover.
I'd like to change color and size of dots too. I tried in many ways but it seems really difficult. Any help?
Here is the piece of code:
svg.selectAll("dot")
.data(data)
.enter().append("circle")
.attr("r", 5.5)
.style("fill", "#fff8ee")
.style("opacity", .8) // set the element opacity
.style("stroke", "#f93") // set the line colour
.style("stroke-width", 3.5)
.attr("cx", function(d) { return x(d.date); })
.attr("cy", function(d) { return y(d.close); })
.on("mouseover", function(d) {
div.transition()
.duration(70)
.style("opacity", .7)
;
div .html(formatTime(d.date) + "<br/>" + d.close)
.style("left", (d3.event.pageX) + "px")
.style("top", (d3.event.pageY - 28) + "px");
})
.on("mouseout", function(d) {
div.transition()
.duration(200)
.style("opacity", 0);
});
Just set color and size in the handlers:
.on("mouseover", function(d) {
d3.select(this).attr("r", 10).style("fill", "red");
})
.on("mouseout", function(d) {
d3.select(this).attr("r", 5.5).style("fill", "#fff8ee");
});
I don't know why, but while d3.select(this) used to work, it doesn't anymore. I now use d3.select(event.currentTarget).
So, if we consider svg as the graph and all its circles being red by default, we can change the color of the circles to green on mouseover and return the color to red on mouseout like this:
svg.on("mouseover", function(d){
d3.select(event.currentTarget)
.style("fill", "green");
})
.on("mouseout", function(d){
d3.select(event.currentTarget)
.style("fill", "red");
});

How do I use enter() correctly in D3.js?

I have some code that create a bunch of circles, updates those circles, removes some of the circles, and lastly I'd like to find out how to use the enter() correctly to add more circles to my current ones.
This is my code for creating circles when there are none:
var circle = SVGbody
.selectAll("circle")
.data(graphDataY/*, function(d){return d;}*/);
circle.enter()
.append("circle");
circle
.attr("cx",xScale(0))
.attr("cy", yScale(minAxisY))
.attr("r",4)
.style('opacity', 0)
.style("fill", colorCircles())
.transition()
.duration(1000)
.attr("cx", function(d, i){ return xScale(graphDataX[i]);})
//.attr("cy", function (d, i){ return yScale(i); })
.style('opacity', 0.8)
.transition()
.duration(1000)
.attr("cy", function(d){return yScale(parseFloat(d));} );
I use the following code to update my circles and remove the ones that aren't being used (sometimes that's the case):
var circle = SVGbody
.selectAll("circle")
.data(graphDataY);
circle
.style("fill", colorCircles())
.transition().duration(1000)
.attr("cx", function(d, i){ return xScale(graphDataX[i]);})
.attr("cy",function(d){return yScale(parseFloat(d));});
circle.exit()
.style("opacity", 1)
.transition()
.duration(300)
.style("opacity", 0)
.remove();
And when lastly, let's assume the last data i used had a length of 100, that means I currently have 100 circles displayed. If I used a new dataset with 120 of length, I use my update code to move the existing circle ( except for the exit().remove() ), and then I try to use the following to "create" the remaining circles out of the remaining unbound data (which in this case would be 20 circles remaining):
circle.enter().append("circle")
.attr("cx", function(d, i){ return xScale(graphDataX[i]);})
.attr("cy",function(d){return yScale(parseFloat(d));})
.style("opacity", 0)
.transition()
.duration(300)
.style("opacity", 1)

Categories

Resources