在 D3 中设置多个属性,而无需提前知道它们将是什么

set multiple attributes in D3 without knowing what they are going to be ahead of time

本文关键字:是什么 设置 D3 属性      更新时间:2023-09-26

我正在绑定在 d3 中设置多个属性,类似于这个答案中所做的:https://stackoverflow.com/a/20822552/1112097,但我希望能够将一组属性作为数组传递,以便相同的代码可以创建不同的元素。例如,以下数据应创建一个红色方块和一个绿色圆圈:

var data = [
  {
    name: "Element 1",
    type: “rect”,
    id: “rect01”,
    attributes: [
     {label: “x”, val: 0},
     {label: “y”, val: 0},
     {label: “width”, val: 10},
     {label: “height”, val: 10},
   ],
   styles: [
     {label: “fill”, val: “none”},
     {label: “stroke”, val: “#ff0000”}
   ]
 },
 {
   name: "Element 2", 
   type: “circle”,
   id: “circle01”,
   attributes: [
     {label: “cx”, val: 30},
     {label: “cy”, val: 30},
     {label: “r”, val: 10}
   ],
   styles: [
     {label: “fill”, val: “#00ff00”},
     {label: “stroke”, val: “#0000ff”}
  ]
  }
];

使用如下所示的内容:

var element = svg.selectAll(".element")
        .data(data, function(d) {return d.id;});
var elementEnter = element.enter()
        .append(function (d) {return d.type;})
        .attr("class", "element")
        .attr({
            // what goes here?
        })
        .style({
            // what goes here?
        }):

我可以用什么来代替"这里有什么?"来设置属性(例如"x"、"cx"或"r"(和使用数据数组的值。

最好将数据

更改为以下格式:

   attributes: { 
     "cx": 0,
     "cy": 30,
     "r": 10
  },
   styles: {
     "fill: "#00ff00",
     "stroke": "#0000ff"
  }

这样你就可以简单地做...

var elementEnter = element.enter()
    .append(function (d) {return d.type;})
    .attr("class", "element")
    .attr(function(d) {return d.attributes});
    .style(function(d) {return d.styles});

如果您仍然想保持当前的格式,您可以执行以下操作...

var elementEnter = element.enter()
    .append(function (d) {return d.type;})
    .attr("class", "element")
    .attr(function(d) {return arrToObj(d.attributes)});
    .style(function(d) {return arrToObj(d.styles)});
function arrToObj(arr) {
   var obj = {};
   arr.forEach(function(keyValue){
     obj[keyValue.label] = keyValue.val;
   });
   return obj;
}

试试这个。

function setAttributesAndStyles(d){
    var attrs = {};
    d.attributes.forEach(function(a){       
        attrs[a.label] =  a.val;
    });
    var styles = {};
    d.styles.forEach(function(a){       
        styles[a.label] =  a.val;
    });
    d3.select(this).attr(attrs);
    d3.select(this).attr(styles);
}
var element = svg.selectAll(".element")
   .data(data, function(d) {return d.id;});
var elementEnter = element.enter()
   .append(function (d) {
      return svg.append(d.type).node(); //Returns the dom element
   })        
   .attr("class", "element")
   .each(setAttributesAndStyles);

请注意,selection.append(name)语句要求名称为常量字符串或返回要追加的 DOM 元素的函数。