Closed alexlenail closed 6 years ago
Yes I don't provide a shapeWidth, the assumption is that you would pass in a larger shape as the path. Do you have an example you could share?
Hi @susielu !
You might have already given me the hint I needed. Right now, I have:
var display_type = d3.scaleOrdinal()
.domain(['protein', 'TF', 'metabolite'])
.range([d3.symbolCircle, d3.symbolTriangle, d3.symbolDiamond] );
svg.append("g")
.attr("class", "legendSymbol")
.attr("transform", "translate(20, 200)");
var legendPath = d3.legendSymbol()
.scale(display_type)
.orient("vertical")
.title("Node Types");
svg.select(".legendSymbol")
.call(legendPath);
Should the scaleOrdinal have some size-related info added to it to fix this?
Yes you should be able to do instead of d3.symbolDiamond
this d3.symbol().type(d3.symbolDiamond).size(100)()
it defaults to 64, see docs: https://github.com/d3/d3-shape#symbols
Thanks @susielu !
I'm concerned this might cause an issue for me... further down I do
node.append("path")
.attr("d", d3.symbol()
.type(function(d) { return display_type(d.type); })
.size(function(d) { return ... }) )
(recall)
var display_type = d3.scaleOrdinal()
.domain(['a', 'b', 'c'])
.range([d3.symbolCircle, d3.symbolTriangle, d3.symbolDiamond] );
I'm concerned that
var triangle = d3.symbol().type(d3.symbolTriangle)(),
circle = d3.symbol().type(d3.symbolCircle)(),
diamond = d3.symbol().type(d3.symbolDiamond)();
var display_type = d3.scaleOrdinal()
.domain(['a', 'b', 'c'])
.range([circle, triange, diamond] );
will cause issues for .type(function(d) { return display_type(d.type); }).size(...)
.
Is there some way I could change some part of this to avoid that issue?
If not, it might make sense to have d3.legendSymbol().scale(...)
to be able to take a scale like my original "display_type
" with .range([d3.symbolCircle, etc..
Hmm not sure I follow, I assume you could just do this and it would work as a legend, maybe I"m missing something in your example?:
var triangle = d3.symbol().type(d3.symbolTriangle).size(10)(),
circle = d3.symbol().type(d3.symbolCircle).size(50)(),
diamond = d3.symbol().type(d3.symbolDiamond).size(100)();
var display_type = d3.scaleOrdinal()
.domain(['protein', 'TF', 'metabolite'])
.range([triangle, circle, diamond] );
svg.append("g")
.attr("class", "legendSymbol")
.attr("transform", "translate(20, 200)");
var legendPath = d3.legendSymbol()
.scale(display_type)
.orient("vertical")
.title("Node Types");
svg.select(".legendSymbol")
.call(legendPath);
@susielu sorry I was unclear. If I do what you suggest, the following code breaks:
node.append("path")
.attr("d", d3.symbol()
.type(function(d) { return display_type(d.type); })
.size(function(d) { return ... }) )
Note that above, display_type
is my scaleOrdinal
. If my scaleOrdinal
is
.range([d3.symbolCircle, d3.symbolTriangle, d3.symbolDiamond] );
Then
.attr("d", d3.symbol()
.type(function(d) { return display_type(d.type); })
evaluates to a symbol type, which is good. But if I change display_type
to have range
.range([triangle, circle, diamond] );
where
var triangle = d3.symbol().type(d3.symbolTriangle).size(10)(),
Then
.type(function(d) { return display_type(d.type); })
throws an error. There might be a solution whereby I can build my scaleOrdinal
the way you do above, and then do something like
.attr("d", d3.symbol()
.type(function(d) { return display_type(d.type).type; })
(notice the last .type
). But I'm not sure.
I want to repeat that it might make sense to have d3.legendSymbol().scale(...)
able to take a scale like my original "display_type
" with .range([d3.symbolCircle, etc..
. What do you think?
So you should be able to use the scale ordinal and change the var with the size like you said:
var triangle = d3.symbol().type(d3.symbolTriangle).size(10)()
And later on when you use the scale instead of
.attr("d", d3.symbol().type(function(d) { return display_type(d.type)})
You should do:
.attr("d",d => display_type(d.type))
since you already evaluated the symbol with a size in the your scale, the range of your scale is already in the string path you need for the "d" property. Does that make sense?
I don't think I'll be able to handle a scale property because by the time I have the symbols in my legend function they're already path strings. Unless you using something like transform to scale it, but then the strokes etc. all get off on size.
This worked! I just need to figure out how to size the nodes now. The issue was that in
var circle = node.append("path")
.attr("d",d => display_type(d.type))
.size(function(d) { return Math.PI * Math.pow(size(d.size) || nominal_base_node_size, 2); })
.style(...
.size returns an int, breaking with what seems like convention to me. =/
This library is awesome! For my purposes, I just want to scale the symbols in my symbol legend so they're a little more visible. I think this is the "ShapeWidth" feature, which is available for color and size legends but not symbol legends?