I want to add the id to the nodes of the graph in the example of
https://d3-graph-gallery.com/graph/network_basic.html
I tried
...
node.append("text")
.attr("dx", 12)
.attr("dy", ".35em")
.text(function(d) { return d.name });
...
but the name does not appear
how can I add the name next to the node
The node variable represents a selection of SVG circles, which cannot contain text elements. You have to use a group element as a parent to hold the circle and the text elements.
First create a selection of group elements that the force simulation will place:
const nodes = svg
.selectAll("g")
.data(data.nodes)
.join("g");
Then add your circle and your text in the groups:
nodes.append("circle")
.attr("r", 20)
.style("fill", "#69b3a2")
nodes.append("text")
.attr("text-anchor", "middle") // text is centered in the circle
.attr("alignment-baseline", "middle")
.text(d => d.name);
Because the force simulation works on group elements, the ticked() function must be adapted to translate them:
nodes.attr("transform", d => `translate(${d.x+6},${d.y-6})`);
See example here: https://codepen.io/ccasenove/pen/eYKzmwd
Related
i've stuck for this code. Im trying to add text behind the circle
and sample code like this
for the text:
g.selectAll(".my-text")
.data(marks)
.enter().append("text")
.attr("class", "text-desc")
.attr("x", function(d, i) {
return projection([d.long, d.lat])[0];
})
.attr("y", function(d, i) {
return projection([d.long, d.lat])[1];
})
.attr('dy', ".3em")
.text(function() { return location})
.attr("text-anchor", "middle")
.attr('color', 'white')
.attr('font-size', 15)
and for circle like this
g.selectAll(".circle")
.data(marktests)
.enter().append("circle")
.attr("class", "bubble")
.attr("cx", function(d, i) {
return projection([d.long, d.lat])[0];
})
.attr("cy", function(d, i) {
return projection([d.long, d.lat])[1];
})
.attr("r", function() {
return myRadius(locationGroup + 20);
})
.on('mouseover', tipBranch.show)
.on('mouseout', tipBranch.hide)
.on('click', function(d){
window.open('http://localhost:8000/detail/'+d.branch);
});
}
but i got result just like this
and the elements if using inspect element
Thank you if you can help to help me and explain how to solve the problem code
First of all I noticed the following issue:
g.selectAll(".my-text")
.data(marks)
.enter().append("text")
.attr("class", "text-desc")
Also the following line: .text(function() { return location}) is faulty because you are missing the data object that you iterate with. This might be changed to: .text(function(d) { return d.location})
you are selecting all elements with class .my-text but then you are attaching text-desc as class to the text elements. The correct change for this would be:
g.selectAll(".text-desc")
.data(marks)
.enter().append("text")
.attr("class", "text-desc")
considering that you want to use text-desc as a class. the same problem is with the circle as well: Either do: g.selectAll("circle") to select the circle tag elements or g.selectAll(".bubble") to select the bubbles.
You are also using different iterating objects for text and circles - usually you should iterate over a single collection.
Another issue with the sample is that location and locationGroup are not part of the collection items. I would expect that the values to be taken from the data object as such .text( d => d.location) and .attr("r", d => myRadius(d.locationGroup)). Before proceeding make sure that you populate iterating items with this properties.
Another approach would be to do the following:
const group =
g.selectAll('.mark')
.data(marks)
.enter()
.append('g')
.attr('class', 'mark')
.attr('transform', d => {
const proj = projection([d.long, d.lat])
return `translate(${proj[0]}, ${proj[1]})`;
})
group.append('text').text(d => return d.location) //apply other props to text
group.append('circle').text(d => return d.location) //apply other props to circle
Using this approach will allow you to iterate the collection with a group element and use translation property in order to move the group to the location (small improvement, projection will be executed once) and use the group to populate with other elements: text, circle.
Hope it helps.
I have some data with 2 attributes: colour and value
I use the D3 enter selection to create circle elements, and append them to the body of the page. Their fill colour is determined by the "colour" attribute.
Then, I append text elements to the page. The text contents are determined by the "value" attribute.
Here is what I am working with:
// Set up svg element
var svg = d3.select("body")
.append("svg")
.attr("width", 300)
.attr("height", 300)
.style("background", "lightblue");
var dataset = [
{"colour":"red", "value":"First set of text"},
{"colour":"green", "value":"Second attempt"},
{"colour":"blue", "value":"Third and final!"}
];
// Create circles from the data
// On mouseover, give them a border (remove on mouseout)
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("r", 40)
.attr("cy", function(d, i) { return i*80 + 40; })
.attr("cx", 50)
.style("fill", function(d) {return d.colour;})
// HERE
// Can I somehow show and hide the text component that is
// associated with this circle when the circle is hovered, rather
// than the text itself?
.on("mouseover", function(d) {
d3.select(this).style("stroke", "black")
.style("stroke-width", 2)
})
.on("mouseout", function(d) {d3.select(this).style("stroke", "none")});
// Now add the text for each circle
// Same thing with mouseover and mouseout
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.attr("text-anchor", "middle")
.attr("y", function(d, i) { return i*80 + 40; })
.attr("x", 50)
.style("opacity", 0)
.on("mouseover", function(d) {d3.select(this).style("opacity", 1)})
.on("mouseout", function(d) {d3.select(this).style("opacity", 0)})
.text(function(d) { return d.value;});
I would like for the text to be hidden, until the associated circle is hovered over. How can I connect the text element with a particular circle, so that I can toggle whether the text is shown by hovering over the circle?
This fiddle below is an outline of what I am trying to do, and what I have got so far. I have the text showing up only when hovered, but not when the circle is hovered.
https://jsfiddle.net/aj4zpn6z/
There are several ways for achieving this. Since both circles and texts use the same dataset, my solution uses filter.
First, let's name the variables for the texts and circles:
var circles = svg.selectAll("circle")
//etc...
var texts = svg.selectAll("text")
//etc...
Then, inside the circles mouseover function, we filter the texts that have the same colour attribute:
.on("mouseover", function(d){
d3.select(this).style("stroke", "black").style("stroke-width", 2);
var tempTexts = texts.filter(function(e){
return e.colour === d.colour
});
tempTexts.style("opacity", 1);
});
This is your updated fiddle: https://jsfiddle.net/wxh95e9u/
So I have points on my SVG map and now I would like to show text next to them. This is a jsfiddle with 2 points and showing their ID text. But as you can see there is no text somehow.
var featureCollection = topojson.feature(topology, topology.objects.testtest);
lines.append("g")
.attr("id", "lines")
.selectAll("path")
.data(featureCollection.features)
.enter().append("path")
.attr("d", path)
.append("text")
.attr("class", "nodetext")
.attr("x", 22)
.attr("y", 4)
.text(function (d) {
return d.properties.id;
});
And I checked it with some other text beside example I already have here. It's working in the same way.
So does it not work with pathes? Could that be?
A 'text' element can't be a child of a 'path' element, it should be a sibling. Group them if they are related and need to be positioned accordingly.
As #liamness says, your text can't be a child of path but needs to be a sibling. Your problem goes a little further, though, since you are using a path and you can't group and position the element conventionally. There is where path.centroid comes in handy. It allows you to find the center of you path and position your text there:
var e = lines.append("g")
.attr("id", "lines")
.selectAll("path")
.data(featureCollection.features)
.enter(); // save enter selection
e.append("path") // add path as child of lines g
.attr("d", path);
e.append("text") // add text as child of lines g, sibling of path
.attr("class", "nodetext")
.attr('x', function(d,i){
return path.centroid(d)[0]; // horizontal center of path
})
.attr('y', function(d,i){
return path.centroid(d)[1] + 13; // vertical center of path
})
.attr('text-anchor','middle')
.text(function (d) {
return d.properties.id;
});
Updated fiddle.
I would like images as the endpoints. I have tried adding but no luck. Any ideas/working examples?
http://bost.ocks.org/mike/uberdata/
Each neighborhood in that example is given a <g> element with a class of group.
// Add a group per neighborhood.
var group = svg.selectAll(".group")
.data(layout.groups)
.enter().append("g")
.attr("class", "group")
.on("mouseover", mouseover);
This is the element to which the text label and the endpoint path are appended.
// Add the group arc.
var groupPath = group.append("path")
.attr("id", function(d, i) { return "group" + i; })
.attr("d", arc)
.style("fill", function(d, i) { return cities[i].color; });
// Add a text label.
var groupText = group.append("text")
.attr("x", 6)
.attr("dy", 15);
You could append each image to this group also, using an svg <image> element. If, for example, your dataset contains the urls for your images, you might do the following:
var groupImage = group.append("image")
.attr("xlink:href", function(d) {return d.image_url;})
I am getting started with D3 and SVG but I haven't found anything clear on how to add hyperlinks. Here is some code I have to write labels to the left of the bars in a D3 bar chart. Is there a good sample somewhere to convert these labels to hyperlinks (say objects in rangeData had an href and name/label property)? I searched around a bit but haven't gotten much further than the svg spec for adding an anchor element.
chart.selectAll(".bar.barLabel")
.data(rangeData)
.enter().append("text")
.attr("class", "bar")
.attr("x", 0)
.attr("y", function (d, i) { return height(i) + barHeight(y, i) / 2; })
.attr("dx", -20)
.attr("dy", ".35em")
.attr("text-anchor", "end")
.text(function (d) { return d.label; });
You can use the a element to achieve this, very similar to HTML itself. You wrap the content in the a element and provide the link target as the href attribute with xlink namespace.
chart.selectAll("a")
.data(rangeData)
.enter()
.append("a")
.attr("xlink:href", function(d) { return d.href; })
.append("text")
.text(function (d) { return d.label; });
Alternatively, you could use the foreignObject element to directly embed HTML into your SVG.