Create a line connecting circles upon mouse hover - d3.js

I have a scatter plot made in D3 with circles denoting each data point. Here's my code:
viz.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr("cx", function(d) {return x(d.x)})
.attr("cy", function(d) {return y(d.y)})
.attr("r", 5)
.attr("fill", function(d) {return d.color})
.on('mouseover', function(d){
console.log(d.color)
})
What I would like to do is, when a given circle is hovered on, connect all circles through a line that have the same color. How can I do this? I can get the color logged into the console, but I don't understand how I can connect all points with the same color through a line upon mouse click?

You can assign a class with color code to your circles. Use d3.selectAll to retrieve all of them on mouseover. Then retrieve their coordinates and pass the coordinates to draw d3.svg.line.
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", function(d) {
return 'dot color-' + color(d.species).replace('#','');
})
.attr("r", 3.5)
.attr("cx", function(d) { return x(d.sepalWidth); })
.attr("cy", function(d) { return y(d.sepalLength); })
.attr("dot-color", function(d) { return color(d.species).replace('#',''); })
.style("fill", function(d) { return color(d.species); })
.on("mouseover", function() {
d3.selectAll(".color-" + $(this).attr("dot-color"))
.attr("r", 5.5);
})
.on("mouseout", function() {
d3.selectAll(".color-" + $(this).attr("dot-color"))
.attr("r", 3.5);
});
Here's an example with color hover:
http://vida.io/documents/KinEKRkSPSfStA4Eu

You can also do it without relying on a common class attribute. In the mouseover handler:
d3.selectAll('.dot')
.filter(function (dOther) { return d.color == dOther.color })
.attr('r', 3.5)

Related

D3.js : Duplicate 100% working interactive legend for a bubble map

I have created a interactive legend, that works 100% perfectly fine. I just didnt manage to duplicate it for another column of my dataframe.
It starts with bubbles I'm plotting with the code below. Then I draw the actual legend.
1. creating bubbles
selection
.selectAll('circle')
.data(cities)
//.attr('r', 14)
.attr('r', function(d) {
return Math.max(Math.pow(d.population, 0.57) / 40, 7);})
.attr('cx', function(d) { return projection.latLngToLayerPoint([d.latitude, d.longitude]).x;
})
.attr('cy', function(d) { return projection.latLngToLayerPoint([d.latitude, d.longitude]).y;
})
.attr("class", function(d) { return "bubbles " + d[attribute] }) //Important feature for legend
//.attr("class", function(d) { return "bubbles " + d.category })
.attr('stroke', 'white')
.attr('stroke-width', function(d) {
return 1.2 / projection.scale;})
.style("fill", function(d) {
return color(d[attribute])})
.attr("stroke", "#FFFF")
.attr("stroke-width", 1)
.attr("fill-opacity", .9)
.on("mouseover", showTooltip)
.on("mousemove", moveTooltip)
.on("mouseleave", hideTooltip)
2. Drawing actual legend
svg_chorop.selectAll("mydots")
.data(allgroups)
.enter()
.append("rect")
.attr("x", 0)
.attr("y", function(d, i) {
return 60 + i * (size + 10)
}) // 60 is where the first dot appears. 10 is the distance between dots
.attr("width", size)
.attr("height", size)
.style("fill", function(d) {
return mycolor(d)
})
.style("stroke", "#DCDCDC")
.on("mouseover", highlight)
.on("mouseleave", noHighlight)
My goal : make the exact same legend with another hovering option.
Problem : I can't find a way to ADD another class attribute (in my case d.category, for economic sector) in the first bunch of code.
Fiddle link, so it's easier for you to see the code : jsfiddle
I have simply tried to add another .attr("class",..). It doesn't work. And I can find a similar fix for this problem online.
.attr("class", function(d) { return "bubbles " + d[attribute] }) //Important feature for legend
//.attr("class", function(d) { return "bubbles " + d.category })
Here you can see the two legends, left one functionnal, right, the
one to be implemented
Here you can see the dataframe and the category column

Line Highlights but dots dont

Im trying to add a 'highlight' effect that is shown in this link(https://www.d3-graph-gallery.com/graph/parallel_custom.html) My lines are made up of two things, first is the line itself, and the second are dots that appear on each line. When my mouse hovers on the red line, the line stays the same but the red dots disapear for some reason. I want the red dots along with the red line to stay the same when i hover over it. What am i doing wrong here? the picture below shows what happens when i hover over the red line, and as you can see the red dots disappear
// Highlight individual line and dots
var highlight = function(d) {
var selected_line = d.key
// first every group turns grey
svgObj.selectAll(".line")
.transition().duration(200)
.style("stroke", "lightgrey")
.style("opacity", "0.2")
svgObj.selectAll(".dot")
.transition().duration(200)
.style("stroke", "lightgrey")
.style("opacity", "0.2")
// Second the hovered line takes its color
svgObj.selectAll("." + selected_line)
.transition().duration(200)
.style("stroke", color(selected_line))
.style("opacity", "1")
svgObj.selectAll("." + selected_line)
.transition().duration(200)
.style("stroke", color(selected_line))
.style("opacity", "1")
}
// UnHighlight
var doNotHighlight = function(d) {
svgObj.selectAll(".line")
.transition().duration(200).delay(50)
.style("stroke", function(d){ return( color(d.key))})
.style("opacity", "1")
}
// Draw the line
svgObj.selectAll(".line")
.data(sumstat)
.enter()
.append("path")
.attr("class", function (d) { return "line " + d.key} ) // 2 class for each line: 'line' and the group name
.attr("fill", "none")
.attr("stroke", function(d){ return color(d.key) })
.attr("stroke-width", 4.5)
.attr("d", function(d){
return d3.line()
.curve(d3.curveMonotoneX)
.x(function(d) { return x(d.year); })
.y(function(d) { return y(+d.n); })
(d.values)
})
//.on("mouseover", function(){return tooltip.style("visibility", "visible");})
//.on("mousemove", function(){return tooltip.style("top", (d3.event.pageY-10)+"px").style("left",(d3.event.pageX+10)+"px");})
//.on("mouseout", function(){return tooltip.style("visibility", "hidden");})
.on("mouseover", highlight)
.on("mouseleave", doNotHighlight )
// Draw dots on points
svgObj.selectAll(".dot")
.data(data)
.enter()
.append("circle")
.attr("class", function (d) { return "dot " + d.key } ) // 2 class for each line: 'line' and the group name
.style("fill","white")
.style("stroke-width", "3px")
.style("stroke", function (d) { return color(d.name) })
.attr("cx", function(d) {return x(d.year); })
.attr("cy", function(d) {return y(d.n); })
.attr("r", 5.5)
It is because the data of .line and .dot is different, one is sumstat with key property, the other one is data without key. so the code
.append("circle")
.attr("class", function (d) { return "dot " + d.key } )
will return "dot undefined" for each circle's class.
And then in highlight() the selected dots will not be included.
I adjusted your code into a demo, but you might change the bind data of .line and .dot consistently, to avoid such mistake after.

Rotate the text placed in map d3.js

Using this I was able to add names to the map: Add names of the states to a map in d3.js
Now, how do I rotate those text as it is overlapping with each other.
For those who are looking for the solution.
Adding this solved it. It produces composition matrix.
.attr('transform', function(d) {
return 'translate('+path.centroid(d)[0]+','+path.centroid(d)[1]+') rotate(-45);
})
Here is the updated code:
function draw(){
d3.json("readme.json", function(json) {
g.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.on("click", click);
g.selectAll("text")
.data(json.features)
.enter()
.append("svg:text")
.text(function(d){
return d.properties.name;
})
// .attr("x", function(d){
// return path.centroid(d)[0];
// })
// .attr("y", function(d){
// return path.centroid(d)[1];
// })
.attr("text-anchor","middle")
.attr('font-size','6pt')
// added
.attr('transform', function(d) {
return 'translate('+path.centroid(d)[0]+','+path.centroid(d)[1]+') rotate(-45);
})
});
}

Warbling circle using d3

I wanted to draw a pulsating warbling circle on a geomap using d3, using this example for guidance. However—and I know this is a very basic question, so apologies—I can't seem to get the selector to fire right. Here is the relevant code:
layer2
.attr("id", "locations")
.selectAll(".state")
.data(columbia.features)
.enter().append("circle")
.attr("class", "location")
.attr("r", "4px")
.attr("cx", function(d) { return proj(d['geometry']['coordinates'])[0]; })
.attr("cy", function(d) { return proj(d['geometry']['coordinates'])[1]; })
.attr("d", path)
.each(pulse);
function pulse() {
var circle = svg.select(".location");
console.log(circle);
(function repeat() {
circle = circle.transition()
.duration(2000)
.attr("stroke-width", 20)
.attr("r", 10)
.transition()
.duration(2000)
.attr('stroke-width', 0.5)
.attr("r", 200)
.ease('sine')
.each("end", repeat);
})();
}
Right now I have:
var circle = svg.select(".location");
What should I have instead of .location?
Here is the full file.
Edit: got it; I need selectAll, notselect.

How to zoom a d3.js DotsChart instead of lineChart

i want zoom a dot chart like a line but each point are duplicated by zoom step.
g.updateCurve = function(_){
// Update the line path.
this.select(".line")
.attr("d", line);
// add each point
this.selectAll('.circle').data(data).enter().append("circle")
.attr("class", "dot")
.attr("cx", function(d) {return xScale (d.date); })
.attr("cy", function(d) {return yScale (d.ySpeed); })
.attr("r", function(d) {return rScale (d.xSpeed); });
return this;
};
how can I change for a proper zoom ?
I work on this JSFiddle
it need to costruct DOM.Circle.data before the update fonction:
g.selectAll('circle').data(data).enter().append("circle")
.attr("class", "dot");
and juste update .attr() on zoom event
// for update Attribute of line and Dots on ZoomEvent
g.updateCurve = function(){
// Update the line path.
this.select(".line")
.attr("d", line);
// add each point
this.selectAll('circle')
.attr("cx", function(d) {return xScale (d.date); })
.attr("cy", function(d) {return yScale (d.ySpeed); })
.attr("r", function(d) {return rScale (d.xSpeed); });
return this;
};
Working exemple on JSFiddle

Resources