I'm attempting to add a simple data label to this example
svg.selectAll("text")
.data(data)
.enter()
.append("text")
.attr("text-anchor", "middle")
.attr("fill", "red")
.text(function(d) { return d[0] });
but it writes all the data in all labels which I think is because the graph is split over several individual svg-elements. How can I fix this?
Fiddle
You're already binding the data to the SVGs, so there's no need for you to bind it again to the text elements. svg is actually the selection of SVGs here, so all you have to do is
svg.append("text")
.attr("text-anchor", "middle")
.attr("fill", "red")
.text(function(d) { return d[0] });
Complete example here.
Related
I have a simple, modified version of the cluster diagram from D3 that I'm trying to get to respond to mouse clicks. It works for the links between nodes but not the nodes themselves. It looks to me like I'm treating lines and nodes (svg circles) the same, and yet nodes do not work... but of course D3 itself is generating those lines...
I have a very simple demo of it on JSFiddle at: http://jsfiddle.net/gaelicmichael1965/c2XWg/8/
What's going on? I would certainly appreciate any help that could be offered.
var nodes = tree.nodes(flareData),
links = tree.links(nodes);
// Create all of the link paths (using diagonal projection)
// Uses D3 functions to create SVG elements
var link = vis.selectAll(".link")
.data(links)
.enter().append("path")
.attr("class", "link")
.attr("d", diagonal)
.on("click", function(d, index) {
console.log("Selected line");
});
// Create all of the g-elements that contain node svg-elements
var node = vis.selectAll(".node")
.data(nodes)
.enter()
.append("circle")
.attr("class", "node")
.attr("r", 4.5)
.attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
// In actuality, will need to access property of d
.style( "fill", function(d, index) { return fillColors[index%4] } )
.on("click", function(d, index) {
console.log("Selected node");
});
The issue you have stems from your CSS. In particular, you are turning off pointer events for the nodes, meaning that mouse-triggered events (such as "click") are not processing:
.node {
font-size: 12px;
pointer-events: none; /*Comment out or remove this line*/
}
Comment out or remove the pointer-events:none; line in your CSS to allow the nodes to be the target of your "click" event.
I have an SVG symbols map I have generated with D3. The map contains over 100 symbols. My question is, How can I add an anchor tag to each individual circle? I will pull the links for each symbol from an external CSV file, but at this point I cannot for the life of me figure out how to add an anchor to each symbol.
My symbols are generated/appended as follows:
circles.selectAll("circles")
.data(schools)
.enter().append("svg:circle")
.attr("cx", function(d,i) {return positions[i][0]})
.attr("cy", function(d,i) {return positions[i][1]})
.attr("r", function(d,i) {return 6})
.attr("i", function(d,i) {return i})
.attr("class", "symbol")
.on("mouseover", function(d,i){
var index = $(this).attr("i");
// console.log(d); ****This is all the data - ie: Name, lat, long, index, state, etc..
return show_bubble(d, index);
}).on("mouseout", function(){
return hide_bubble();
}).on("mousemove", function() {
return move_bubble();
})
I have tried:
d3.selectAll("#circles")
.append("a")
.attr("href", "google.com");
This, however simply wraps my entire group containing the symbols in an anchor tag.
Please help!
The way I usually do text in circles is I do another binding of the data, but instead of appending a circle, I would append text.
So the code could look like this:
circles.selectAll("circle-text")
.data(schools)
.enter().append("text")
.attr("x", function(d,i) {return positions[i][0]})
.attr("y", function(d,i) {return positions[i][1]})
.text( function (d) { return "Hello World" });
And then if you want anchor tags instead of plain text, try reading this example: Hyperlinks in d3.js objects
It seems you need a special element: "svg:a" in order to create hyperlinks.
Hope this helps.
I have generated a map of Phoenix from this GeoJson and made it show as I would like it to.
Now I would like to add circles to the map to represent something of interest, but the circles never show up. Here is the code:
<script type="text/javascript">
var h = 1280;
var w = 1280;
var projection = d3.geo.albers().scale(80000).center([0, 33.44]).rotate([112.07, 0]).translate([920, 850]);
var path = d3.geo.path().projection(projection);
var svg = d3.select("body").append("svg").attr("width", w).attr("height", h);
d3.json("data/phoenix.json", function(json) {
svg.selectAll("path").data(json.features).enter().append("path")
.attr("d", path).style("fill", "grey");
var coordinates = projection([33.46764,112.0785]);
svg.append("circle")
.attr("cx", coordinates[0])
.attr("cy", coordinates[1])
.attr("r", 5)
.style("fill", "red");
});
</script>
I have tried following different tutorial and howto's like from bost.ocks.org and this where it's with a csv file, but no matter what I do it won't draw the circle, what am I missing?
Adam Pearce is correct that the coordinates are [33.46764, -112.0785], however there is another problem: when translating from lat-long to the coords, you need to pass longitude as the first parameter, not latitude!
The tricky thing is that the albers projection, if called with a value not in (lower 48, alaska, hawaii) returns null silently.
Trying to translate [33.46764, -112.0785] in the console:
> proj = d3.geo.albersUsa()
function albersUsa(coordinates) {
var x = coordinates[0], y = coordinates[1];
point = null;
(lower48Point(x, y), point) || (alaskaPoint(x, y), point) || hawaiiPoint(x, y);
return point;
} d3.v3.js:3257
> proj( [33.46764, -112.0785] )
null
> proj( [-112.0785, 33.46762] )
[241.08874867733104, 327.6295325563234]
Bingo. In this case, it was useful to take a look at the actual function we are calling by using the console (in this case, in Chrome).
This was done using d3 version 3.3.8.
Schimmy's answer is correct, however I didn't understand at first. Here's how I added a circle on an Albers map:
//var projection = d3.geo.albersUsa();
var coordinates = projection([-112.0785,33.46764]);
svg.append("circle")
.attr("cx", coordinates[0])
.attr("cy", coordinates[1])
.attr("r", 5)
.style("fill", "red");
You may also want to use attr("transform", "translate") rather than attr("cx", coor[0].attr("cy", coor[1]).
If you have a GeoJson fie of the US and you want to plot a circle on each county:
// us = the geoJson file
svg.append("circle")
.data(topojson.feature(us, us.objects.counties).features)
.enter().append("circle")
.attr("transform", function(d) { return "translate(" + path.centroid(d) + ")"; })
.attr("r", 5)
.style("fill", "red");
You may find this much more efficient than "cx" and "cy".
From http://bost.ocks.org/mike/bubble-map/
I'm using D3.js. I want to show a tooltip with corresponding Y-axis value when i mouseover d3.svg.line().
I tried using this code:
d3.svg.line().append("title")
.text(function(d) { return d; });`
but it throws error has no method 'append'. Is there any other way?
d3.svg.line() is a line generator; it is not the actual line element. This function is designed to work with an area generator, though you can disable the appearance of the shape within by using "fill:none." For more detailed information, here is a link to its documentation: https://github.com/mbostock/d3/wiki/SVG-Shapes#wiki-line.
The code below creates a path element using the d3.svg.line() generator and then adds a tooltip to the path it generates. This title's text attribute shows the y-value of wherever the mouse is. This is done by using the mouse event "mousemove" which seems to be more what you want instead of using "mouseover." (Mouseover requires you to move in and out of the shape to update the text value, whereas mousemove will change the value even if your mouse moves along the line.)
var data = [[{x:100, y:200}, {x:0,y:400}, {x:2, y:300}]];
var line = d3.svg.line()
.x(function(d) { return d.x; })
.y(function(d) { return d.y; })
.interpolate("basis");
var svg = d3.select("body").append("svg:svg")
.attr("width", 400)
.attr("height", 400);
var g = svg.selectAll("g").data(data).enter().append("svg:g")
.attr("width", 400)
.attr("height", 400);
g.append("path")
.attr("d", line)
.attr("id", "myPath")
.attr("stroke", "black")
.attr("stroke-width", 5)
.attr("fill", "none") // Remove this part to color the
// shape this path produces
.on("mousemove", mMove)
.append("title");
function mMove(){
var m = d3.svg.mouse(this);
d3.select("#myPath").select("title").text(m[1]);
}
There was a little error in your answer.
d3.svg.mouse(this)
doesn't work.
The correct answer is
d3.mouse(this)
I am working on a bubble graph and I have attached an on click event to each of the circles. When clicking on a circle, the bubble graph will be replaced with a new graph representing a more detailed information.
Here is part of the code:
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return scaleX(d[2]);
})
.attr("cy", function(d) {
return scaleY(100 - d[1]);
})
.attr("r", function(d) {
return d[1];
})
.attr("fill", "#4eb157")
.attr("stroke", "#00c4d4")
.attr("stroke-width", function(d) {
return d[1]*(1-d[2]/100)*1.5;
})
.on("click", function ()
{
svg.selectAll("circle")
.data(new_dataset)
.enter()
.append("circle")
.attr("cx", function(d) {
return scaleX(d[2]);
})
.attr("cy", function(d) {
return scaleY(100 - d[1]);
})
.attr("r", function(d) {
return d[1];
})
.attr("fill", "#4eb157")
.attr("stroke", "#00c4d4")
.attr("stroke-width", function(d) {
return d[1]*(1-d[2]/100)*1.5;
});
svg.selectAll("text")
.data(new_dataset)
.enter()
.append("text")
.text(function(d) {
return d[0];
})
.attr("x", function(d) {
return scaleX(d[2]);
})
.attr("y", function(d) {
return scaleY(100 - d[1]);
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red");
});
The problem comes when I click on the circle, the whole graph disappears, but no new graph is visualized. I figured out that during the execution of the on click function, the svg object has changed from its initial state and in particular some of the properties such as baseURI, clientHeight, clientWidth etc are not set anymore even though they were when initially creating the svg object. Here is the code with which I am creating the svg object:
var svg = d3.select("body").append("svg")
.attr("width", w)
.attr("height", h);
My question is why is the new graph not appearing? Is this because of the changed properties of the svg object? What should I change in the on click function in order to make the new graph visualize successfully?
Thanks!
The problem is that in the onclick event you are selecting all the circles under the svg element and joining them with new_dataset. You probably want to select another set of circle elements and join new_dataset to this group of circles. One way to do that is to create two groups under svg, one for the original set, and other for the circles of new_dataset, another solution is to assign different classes to different groups of circles and narrow each selection using the class.
In the following links you can find a clearer explanation about the joining mechanism:
D3 Tutorial - Scott Murray
Thinking with Joins - Mike Bostok