admin管理员组文章数量:1417070
I am trying to get the legend of my chart outside of the charting area.
Here are the margins:
var margin = {top: 50, right: 200, bottom: 50, left: 40};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
First I create the svg:
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
So, from my understanding, I now have the svg canvas element and a g inside of it which holds the chart. I am trying to add more to the right margin, so I can get some space between the svg canvas and the g appended to it, which holds the chart. Then I want to put my legend in that empty space.
Here is where I add my legend:
//add legend
var legend = svg.append("g")
.attr("class", "legend")
.attr("height", 300)
.attr("width", 200)
.attr("transform", "translate(-1000,50");
Even though I am appending to the SVG element, it is appending to the g within the svg element. So, no matter how much I translate it or try to get it to go more right on the screen, it never goes past the width of the inner g.
When troubleshooting, I see that the outer SVG element has a height of 960 and width of 500. The g appended to that has a transform/translate of 40,50. The width ends up being 839px by 433.223px (not sure I understand this). The outer svg has a bunch of space to the right now because of the margin built in.
So I'm trying to either increase the width of the g appended to the svg so I can put my legend as a child of the g and move it to the empty space created by the margin. Or, I'm trying to create another g that is a sibling to the first g and then I can use the empty space created by the margin.
I can't get either to work and don't know which way is best.
I am trying to get the legend of my chart outside of the charting area.
Here are the margins:
var margin = {top: 50, right: 200, bottom: 50, left: 40};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
First I create the svg:
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
So, from my understanding, I now have the svg canvas element and a g inside of it which holds the chart. I am trying to add more to the right margin, so I can get some space between the svg canvas and the g appended to it, which holds the chart. Then I want to put my legend in that empty space.
Here is where I add my legend:
//add legend
var legend = svg.append("g")
.attr("class", "legend")
.attr("height", 300)
.attr("width", 200)
.attr("transform", "translate(-1000,50");
Even though I am appending to the SVG element, it is appending to the g within the svg element. So, no matter how much I translate it or try to get it to go more right on the screen, it never goes past the width of the inner g.
When troubleshooting, I see that the outer SVG element has a height of 960 and width of 500. The g appended to that has a transform/translate of 40,50. The width ends up being 839px by 433.223px (not sure I understand this). The outer svg has a bunch of space to the right now because of the margin built in.
So I'm trying to either increase the width of the g appended to the svg so I can put my legend as a child of the g and move it to the empty space created by the margin. Or, I'm trying to create another g that is a sibling to the first g and then I can use the empty space created by the margin.
I can't get either to work and don't know which way is best.
Share Improve this question asked Feb 26, 2016 at 20:50 strahanstoothgapstrahanstoothgap 1632 silver badges8 bronze badges 2- g elements don't have width and height attributes, they alwaysautosize to contain their children – Robert Longson Commented Feb 26, 2016 at 23:01
- Your first statement does not return the 'svg' but is instead returning the appended 'g'. That is why your legend statement nests the next g under the the first. d3 uses method chaining so calling .append() returns the new selection. Fix by breaking your svg creation statement into two separate statements, one creating the 'svg' and then another creating the 'g' for your chart. – Nathan Reese Commented Feb 26, 2016 at 23:05
2 Answers
Reset to default 5Notice that the var svg
is being assigned to a <g>
nested inside the <svg>
svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g") // <-- This is what svg is currently being assigned to
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
And so, when you later execute var legend = svg.append("g")
, you're actually appending the legend as a child of the aforementioned <g>
. And that's what you described seeing in the dev tools.
One implication is that the translate()
transform you applied to the outer <g>
affects the inner <g>
(i.e. the translation of the innter <g>
of legend
is added to that of the outer <g>
).
Likely, you want split things up like so:
var svg = d3.select("body").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
var inner = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
Then change your code to draw the existing chart into inner
rather than svg
.
As a result, var legend = svg.append("g")
will append legend as a sibling of inner
, and any translation you apply to legend
would be relative to the svg's top left (as opposed to inner
's top left, which is translated by margin
)
And likely you want to translate legend
like so:
var legend = svg.append("g")
.attr("transform", "translate(" + width - margin.right + "," + margin.top + ")");
That moves the legend to the right end of the chart, MINUS margin.right
. That way, you can tweak margin.right
to create enough room for legend
.
Finally, note that calling
legend
.attr("height", 300)
.attr("width", 200)
doesn't do anything, because for svg <g>
, there isn't a way to explicitly set the width and height. Those wouldn't mean much anyway, because svg doesn't have a the "flow" behavior of html layouts. The width and height shown in dev tools are the implicit bounds resulting from the bounds of the children of the <g>
. (If needed, there's a way to get those puted bounds in javascript, using the getBBox()
function).
by looking at the code you provided, you are actually attaching the legend var to your group "g", instead of "svg",
var legend = svg.append("g")
in this line you are telling d3 to get your legend variable to "g" which is append to svg, if i understand correctly you should try something like this:
var legend = svg.selectAll(".legend")
.enter().append("g")
to create another group "g" for your legends. i apologize for my bad english.
本文标签: javascriptd3js Get Legend Outside of ChartStack Overflow
版权声明:本文标题:javascript - d3.js Get Legend Outside of Chart - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745258279a2650233.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论