简体   繁体   English

使用绑定到多个组元素的数据来绑定新元素的更优雅的方法

[英]A more elegant way to bind new elements using data bound to multiple group elements

When working with d3.js I often encounter the situation where I would like to create some groups that contain specific parts of my data set.在使用 d3.js 时,我经常遇到这样的情况:我想创建一些包含数据集特定部分的组。 These groups are then used to bound some other elements to it after transforming the data contained by the groups with some function.然后,在使用某些函数转换组包含的数据之后,这些组用于将一些其他元素绑定到它。 I have been searching for an elegant situation for a while, but haven't found one yet.我一直在寻找一种优雅的情况,但还没有找到。 I now use the each function, but I reckon there must be a better way to do this.我现在使用 each 函数,但我认为必须有更好的方法来做到这一点。 If anyone knows of a better way to do this, it would be greatly appreciated.如果有人知道更好的方法来做到这一点,将不胜感激。

d3.json("example.json").then(data => {
  d3.select("#A")
    .append("svg")
    .attr("id", "A_SVG")
    .attr("width", width)
    .attr("height",height);
  d3.select("#A_SVG")
    .append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`)
    .attr("id", "A_CHART");
  d3.select("#A_CHART")
    .selectAll(".stateProperty")
    .data(Object.entries(data["A"]))
    .enter()
    .append("g")
    .attr("class", "stateProperty")
    .attr("transform", (d, i) => `translate(0,${i * rowSpacing})`);
 d3.select("#A_CHART")
    .selectAll(".stateProperty")
    .each(function(d) {
      d3.select(this)
        .selectAll("rect")
        .data(getNotHoldsRectValues(d[1]))
        .enter()
        .append("rect");
    });
});

function getNotHoldsRectValues(data) {
return [data[0],data[1]]
}

example.json:示例.json:

{
  "A": {
    "tick_update": [
      { "holds": 1535602060 },
      { "not_holds": 1535602070 },
      { "holds": 1535602120 },
      { "not_holds": 1535602130 }
    ],
    "some_property": []
  },
  "B": {
    "tick_update": [
      { "holds": 1535602060 },
      { "not_holds": 1535602070 },
      { "holds": 1535602120 },
      { "not_holds": 1535602130 },
      { "holds": 1535602180 },
      { "not_holds": 1535602610 }
    ],
    "some_property": []
  }
}

It turns out that the "elegant" way is just the default, idiomatic way.事实证明, “优雅”的方式只是默认的、惯用的方式。

First, avoid selecting elements all the time.首先,避免一直选择元素。 That's a slow process.这是一个缓慢的过程。 Instead of that, name your selections and use them.取而代之的是,命名您的选择并使用它们。

So, this...所以这...

d3.select("#A")
    .append("svg")
    .attr("id", "A_SVG")
    .attr("width", width)
    .attr("height",height);
d3.select("#A_SVG")
    .append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`)
    .attr("id", "A_CHART");

Becomes:变成:

const svg = d3.select("#A")
    .append("svg")
    .attr("id", "A_SVG")
    .attr("width", width)
    .attr("height",height);

svg.append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`)
    .attr("id", "A_CHART");

That way, you just need to use your new const svg whenever you want to refer to that selection.这样,您只需要在想要引用该选择时使用新的 const svg That can be applied to all sub-selections.这可以应用于所有子选择。

Secondly, there is no need for an each here, simply call the enter selection in the group you want.其次,这里不需要each ,只需在您想要的组中调用输入选择即可。

All that being said, this could be your code:话虽如此,这可能是您的代码:

d3.json("example.json").then(data => {
  const svg = d3.select("#A")
    .append("svg")
    .attr("id", "A_SVG")
    .attr("width", width)
    .attr("height", height);
  const g = svg.append("g")
    .attr("transform", `translate(${margin.left},${margin.top})`)
    .attr("id", "A_CHART");
  const myGroups = g.selectAll(null)
    .data(Object.entries(data["A"]))
    .enter()
    .append("g")
    .attr("class", "stateProperty")
    .attr("transform", (d, i) => `translate(0,${i * rowSpacing})`);
  const rects = myGroups.selectAll(null)
    .data(getNotHoldsRectValues(d[1]))
    .enter()
    .append("rect");
});

Here I'm using selectAll(null) , assuming you don't have an update selection.这里我使用selectAll(null) ,假设您没有更新选择。

Finally, it's not clear to me why you are using Object.entries() and that getNotHoldsRectValues function.最后,我不清楚您为什么使用Object.entries()getNotHoldsRectValues函数。 That might be worth a new question.这可能值得一个新问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM