I would like to make the text in the D3.js nodes submit a GET request upon click.
The jsfiddle for the code can be found here: https://jsfiddle.net/ft5107wo/2/
I would like the GET request to be on the id key in node's JSON.
I have attempted this solution, but it did not work.
The relevant code for creating the rectangles and appending node text is from lines 191 to 218, and is as follows:
// Create the node rectangles.
nodes.append("rect")
.attr("class", "node")
.attr("height", 40)
.attr("width", 40)
.attr("id", function (d) {
return d.id;
})
.attr("display", function (d) {
if (d.hidden) {
return "none"
} else {
return ""
};
})
.attr("x", kx)
.attr("y", ky);
// Create the node text label.
nodes.append("text")
.text(function (d) {
return d.name;
}).attr("transform", "translate(0," + 5 + ")")
.style("text-anchor", "middle")
.attr("x", tx)
.attr("y", ty)
.attr("dy", 0)
.call(wrap, 40);
How can this be achieved?
It turns out one needs to use this hack to have it work correctly and avoid problems with namespaces.
Related
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
I was trying to add labels to circles that are constantly moving in D3. One of the ways I found was to insert the label and the circle to a g tag. However, this causes errors whenever I want to EXIT the elements and merge them (which is not happening right now).
Is there any other way to do it? My graph right now seems to be with lower frames per second because it is not using the merge to update from the current x/y position to the new one.
The code is as follow:
var t = d3.transition()
.duration(0);
// JOIN new data with old elements.
var circles = g.append("g").selectAll('g')
.data(data.values)
.enter()
.append('g')
// EXIT elements
d3.selectAll("circle").transition()
.attr("class", "exit")
.remove();
// EXIT elements
d3.selectAll(".label")
.attr("class", "exit")
.remove();
// ENTER new elements present in new data.
// Circles
circles.append("circle")
.attr("class", "enter")
.attr("fill", function (d) { return color(d.country); })
.attr("cy", function (d) { return y(d.active_cases); })
.attr("cx", function (d) { return x(d.total_deaths) })
.merge(circles)
.transition(t)
.attr("r", 15)
// Labels
circles.append("text")
.attr("class", "label")
.attr("font-size", 10)
.style("text-anchor", "middle")
.style("fill", "white")
.attr("x", function (d) { return x(d.total_deaths) })
.attr("y", function (d) { return 3 + y(d.active_cases) })
.merge(circles)
.text(function (d) { return d.country })
I am struggling to add vertical labels to the individual bars in a D3 Version 4 chart. I think the problem is that the <text> element cannot be within the <rect> element according to SVG standards but for the life of me, I cannot work out how to have the <text> element appear just outside the <rect> element. Problematic code is here:
g.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("y", function(d) { return y(d.Country); })
.attr("x", function(d) { return x(d.freqStart); })
.attr("width", function(d) { return x(d.freqEnd) - x(d.freqStart); })
.attr("height", y.bandwidth())
.append("text")
.attr("class", "label")
.attr("transform", "rotate(-90)")
.text(function(d) { return d.Operator; });
The full code can be found at
https://plnkr.co/edit/JiuYKhRxgqtG1osYjJHq?p=preview
Yes, you are right. <text> elements cannot be inside <rect> elements. Technically, you can append them but you wont see anything.
That being said, the common way to do this is to append your rects to a <g> element. This way, you can add text labels to the corresponding group accordingly.
This is the portion of your code that I changed. For each bar, we append a new <g> element. In the second part of the code, we add the text labels to the same g elements.
g.selectAll(".bar")
.data(data)
.enter().append("g")
.attr("class", "bars")
.append("rect")
.attr("class", "bar")
.attr("y", function(d) { return y(d.Country); })
.attr("x", function(d) { return x(d.freqStart); })
.attr("width", function(d) { return x(d.freqEnd) - x(d.freqStart); })
.attr("height", y.bandwidth());
var bars = svg.selectAll(".bars");
bars.append("text")
.attr("class", "label")
.attr('transform', 'rotate(-90)')
.attr("y", function(d) { return x(d.freqStart) + 20; })
.attr("x", function(d) { return -y(d.Country) + 5; })
.text(function(d) { return d.Operator; });
Full working code here - https://plnkr.co/edit/9rUZXl7mfw32sWJih2Ob?p=preview
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");