d3.js获取图表之外的图例

str*_*gap 6 javascript svg 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;
Run Code Online (Sandbox Code Playgroud)

首先我创建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 + ")");
Run Code Online (Sandbox Code Playgroud)

所以,根据我的理解,我现在拥有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");
Run Code Online (Sandbox Code Playgroud)

即使我附加到SVG元素,它也会附加到svg元素中的g.因此,无论我翻译多少或尝试让它在屏幕上更加正确,它永远不会超过内部g的宽度.

在进行故障排除时,我看到外部SVG元素的高度为960,宽度为500.附加的g的变换/转换为40,50.宽度最终为839px乘433.223px(不确定我理解这一点).由于内置边距,外部svg现在有一堆空间.

所以我试图增加附加到svg的g的宽度,这样我就可以将我的图例作为g的子项并将其移动到边距创建的空白区域.或者,我正在尝试创建另一个g,它是第一个g的兄弟,然后我可以使用边距创建的空白空间.

我不能上班,也不知道哪种方式最好.

mee*_*mit 5

请注意,varsvg被分配给<g>嵌套在<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 + ")");
Run Code Online (Sandbox Code Playgroud)

因此,当您稍后执行时var legend = svg.append("g"),您实际上是将图例附加为上述的子项<g>. 这就是您在开发工具中所描述的。

一个含义是,translate()改变你施加在外<g>影响内<g>(即innter翻译<g>legend被添加到外的<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 + ")");
Run Code Online (Sandbox Code Playgroud)

然后更改您的代码以将现有图表绘制成inner而不是svg.

因此,var legend = svg.append("g")将附加图例作为 的兄弟inner,并且您应用的任何翻译legend都将相对于 svg 的左上角(与 的左上角相反inner,由margin

并且您可能想这样翻译legend

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

这会将图例移动到图表的右端 MINUS margin.right。这样,您可以进行调整margin.right以创建足够的空间legend.

最后,请注意调用

legend
  .attr("height", 300)
  .attr("width", 200)
Run Code Online (Sandbox Code Playgroud)

不做任何事情,因为对于 svg <g>,没有办法明确设置宽度和高度。无论如何,这些都没有多大意义,因为 svg 没有 html 布局的“流”行为。开发工具中显示的宽度和高度是由<g>. (如果需要,有一种方法可以使用该getBBox()函数在 javascript 中获取这些计算边界)。