2016-02-26 67 views
5

我正在尝试在图表区域之外获取图表的图例。d3.js获取图表以外的图例

这里有边距:

var margin = {top: 50, right: 200, bottom: 50, left: 40}; 
     var width = 960 - margin.left - margin.right, 
      height = 500 - margin.top - margin.bottom; 

首先,我创建了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 + ")"); 

所以,从我的理解,我现在有SVG canvas元素和Ag它里面持有的图表。我正在尝试向右边添加更多,所以我可以在svg画布和附加到它的g之间留出一些空间,该空间用于保存图表。然后我想把我的传奇放在那个空白的空间里。

这里就是我加入我的传说:

//add legend 
      var legend = svg.append("g") 
       .attr("class", "legend") 
       .attr("height", 300) 
       .attr("width", 200) 
       .attr("transform", "translate(-1000,50"); 

即使我追加到SVG元素,它被附加到SVG元素中的克所以,无论我翻译多少或试图让它在屏幕上更加正确,它永远不会超过内部g的宽度。

排除故障时,我看到外部SVG元素的高度为960,宽度为500.附加到g的元素具有40,50的变换/平移。宽度最终为839像素433.223像素(不知道我明白这一点)。外部svg现在有一堆空间,因为内置了保证金。

所以我试图增加g的宽度,所以我可以把我的传奇作为孩子的g并将其移动到由边距创建的空白区域。或者,我正在尝试创建另一个g,它是第一个g的兄弟,然后我可以使用边距创建的空白空间。

我无法上班,也不知道哪条路最好。

+0

g元素没有宽度和高度属性,他们总是放大以包含他们的子女 –

+0

您的第一条语句不会返回'svg',而是返回附加的'g'。这就是为什么你的传奇语句嵌套在第一个下面的下一个g。 d3使用方法链接,所以调用.append()返回新的选择。通过将您的svg创建语句分成两个单独的语句来修复,一个是创建'svg',另一个是为您的图表创建'g'。 –

回答

2

注意,当你以后执行var legend = svg.append("g"),你实际上是附加的传说作为上述<g>的孩子。这就是你所描述的在开发工具中看到的。

一个含义是所述translate()变换你施加到外<g>影响内<g>(即,所述的innter legend<g>被添加到外<g>的翻译)。

可能的是,你要拆东西,像这样:

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 + ")"); 

然后改变你的代码,以现有的图表绘制成inner而非svg

结果,var legend = svg.append("g")将追加传说的那样的inner兄弟,和(相对于inner的左上角,这是由margin翻译)

您申请 legend任何翻译是相对于SVG的左上角

而且可能要像这样翻译legend

var legend = svg.append("g") 
       .attr("transform", "translate(" + width - margin.right + "," + margin.top + ")"); 

即移动图例到图表的右端,减去margin.right。这样,您可以调整margin.rightlegend创建足够的空间。

最后,注意调用

legend 
    .attr("height", 300) 
    .attr("width", 200) 

没有做任何事情,因为对SVG <g>,没有明确设置宽度和高度的方式。这些并不意味着太多,因为svg没有html布局的“流动”行为。开发工具中显示的宽度和高度是由<g>的子项的边界产生的隐式边界。 (如果需要,有一种方法可以使用getBBox()函数在javascript中获得这些计算的边界)。

-1

通过查看您所提供的代码,你实际上是在这条线连接传说VAR到组“G”,而不是“SVG”,
var legend = svg.append("g")

你告诉D3让你的传奇变数以“G”,这是附加到SVG,如果我理解正确的,你应该尝试这样的事:

var legend = svg.selectAll(".legend") 
.enter().append("g") 

创建另一个组“G”为你的传说。 我为我的坏英语道歉。该变种svg被分配到嵌套在<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 + ")"); 

所以里面<g>