Reputation: 1604
I have a dataset displayed on a D3JS scatter plot. Basically, points of the dataset are (x, y, category) and I would like to plot "Category A" as orange circles and "Category B" as blue triangles.
[TODAY] colors are ok but all points are circles :
[ ... ]
var color = d3.scale.ordinal()
.domain(["Category A", "Category B"])
.range(["#f76800", "#000066"]);
// draw dots
svg.selectAll(".dot")
.data(data)
.enter().append("circle")
.attr("class", "dot")
.attr("r", 7)
.attr("cx", xMap)
.attr("cy", yMap)
.style("fill", function(d) {
return color(d.category);
;})
[ ... ]
I found this thread Triangle scatter plot with D3.js so I was trying - with not much success - something like :
[ ... ]
var color = d3.scale.ordinal()
.domain(["Category A", "Category B"])
.range(["#f76800", "#000066"]);
// draw dots
svg.selectAll(".dot")
.data(data)
.enter().append((d.category == "Category A") ? "circle":"path")
.attr((d.category == "Category A") ? "CIRCLE attr":"TRIANGLE attr")
.style("fill", function(d) {
return color(d.category);
;})
[ ... ]
Is it a reasonable try ?
EDIT : Attempt
[ ... ]
svg.selectAll(".dot")
.data(data)
.enter().append((d.category == "A") ? "path":"circle")
.attr((d.category=="A") ? ({"d":d3.svg.symbol().type("triangle-up"), "transform":"translate(" + xMap + "," + yMap + ")"}):({"class":"dot", "r":7, "cx":xMap, "cy":yMap}))
.style("fill", function(d) {
return color(d.category);
;})
.style("opacity", .95 )
.style("stroke-width", function(d) {
if (d.category == "A") {return 0.95}
else { return 0 }
;})
[ ... ]
Result : "ReferenceError : d is undefined" in Firebug console
Edit 2 - data subset
May this help : to see the full code, here is the actual website : http://www.foolset.com/SNES.php?Jeu=Whirlo . Note that field "d.category" mentioned here for educational purpose, is in fact "d.site".
Data subset : Data come from a MySQL request, fields include : "prix" (for Y value), "date" (for X value), and "site" i.e. category above. Other fields are irrelevant here. Please find a data subset here : http://www.pastebin.com/khdXCSNx
Upvotes: 0
Views: 1852
Reputation: 21578
Instead of expressions you need to provide callbacks to .append()
and .attr()
much like you did for the call to .style()
. Because the expressions will get evaluated only once when the functions are called, these will provide constant values for all points. That's why the colors, i.e. style("fill", function() {})
, are ok, whereas the shapes are not. Furthermore, it's an explanation for the ReferenceError complaining about d
being undefined
.
Although the callback will work pretty well for .append()
, I doubt there is an easy solution for setting the attributes this way.
svg.selectAll(".dot")
.data(data)
.enter().append(function(d) { // This needs to be a callback, too.
var type = d.category == "Category A" ? "circle" : "path";
// In this case, you need to create and return the DOM element yourself.
return document.createElementNS("http://www.w3.org/2000/svg", type);
})
.attr(
// Not sure, if there is an easy solution to setting the attributes.
)
.style("fill", function(d) { // This one already uses a callback function.
return color(d.category);
;})
Your approach seems to be overly complicated and feels like a dead-end road. I suggest sticking to the example you linked to, which makes use of the d3.svg.symbol()
path generator which supports both circles and triangles by setting the appropriate type.
svg.selectAll(".dot")
.data(data)
.enter().append("path")
.attr("d", d3.svg.symbol().type(function(d) {
return d.category == "Category A" ? "triangle-up" : "circle";
}))
.attr("transform", function(d) {
return "translate(" + xMap(d) + "," + yMap(d) + ")";
});
Upvotes: 2