如何使用数据对象中的值指定d3.js选择器?

时间:2014-02-02 17:45:47

标签: javascript d3.js

我在网络应用程序中使用d3.js。描述我想要做的最简单的方法是查看下面链接的小提琴,但基本设置是我有一个包含数据对象的数组。

my_data = [{
    id: "B",
    text: "I want this text in B"
}, {
    id: "C",
    text: "I want this text in C"
}];

我想将my_data中的“text”值添加到DOM中相应的<div>,这是my_data中相应“id”指定的值。也就是说,DOM包含一个id为“B”的div,而my_data包含一个id为“B”的对象,所以我想将“text”属性的值添加到<div>,比如说一个<p>元素。

现在问题。

如何在不知道的情况下编写我的d3选择器以使用my_data中的“id”属性 my_data包含哪些值? (即,我不想对它们进行硬编码!) 我正在使用动态数据源,my_data经常使用 改变。我想使用d3将“text”属性添加到相应的<div>。 我们保证my_data中的“id”属性将具有相同ID的<div> 已存在于DOM中。

最小的例子: http://jsfiddle.net/3Skq3/1/

4 个答案:

答案 0 :(得分:0)

传递给d3.select的选择器只是字符串。因此,您可以使用属性的值,并将连接它与选择器的其他部分一起使用。例如:

d3.select('#' + my_data[0].id)

答案 1 :(得分:0)

这是一种稍微多一点的D3方式。我们的想法是使用您可以匹配数据阵列的数据预填充div s,以“过滤”您想要的节点。这有点人为,但是你可以使用D3的数据匹配来完成这项工作。

d3.selectAll("div")
  .each(function() { this.__data__ = { id: this.id }; })
  .data(my_data, function(d) { return d.id; })
  .text(function(d) { return d.text; });

.each()通过获取当前ID将数据绑定到元素。这通常是通过D3中的.data()来完成的,但我们必须在这里破解它,因为元素已经存在。在那之后,它很简单。完整示例here

答案 2 :(得分:0)

这类似于Lars的建议,但如果你的页面上有很多<div>并且只有少数人会被操纵,那么效率会更高。

首先,选择所有<div>元素,然后根据您的数据数组选择filter that selection。然后,您只使用您拥有数据的元素。使用key:value对象中的数据可以更快地运行,但您也可以在过滤器测试中使用array.some()

var dataMap = {};
my_data.forEach(function(d){dataMap[d.id] = d;})

d3.selectAll("div")
  .filter(function(){ return !!dataMap[this.id]; }) 
      //returns true if the element's id is in the data
  .text(function(){ return dataMap[this.id].text; })

如果您要做的不仅仅是设置文本,那么您需要使用.datum(function(){ return dataMap[this.id]; })将数据绑定到元素。

答案 3 :(得分:0)

我已使用您的示例和http://bost.ocks.org/mike/bar/

上的教程创建了一个代码段

要更改文字,您可以随时拨打此电话。

d3.select('#B').text('Now I want to B');

虽然你想要一个更动态的解决方案这个功能应该有所帮助。

  function getObjByValue(myRoot, myType, myVal, newText){
    var d;
    console.log(typeof myRoot)
    if(typeof myRoot == "object"){
      for(d in myRoot){
        console.log(myRoot[d][myType])
        if(myRoot[d][myType] == myVal){
          d3.select('#'+myVal).text([newText]);
        }
      }
    }
  } 

getObjByValue(data, 'id', 'B', 'Now I want to B');

改编自https://gist.github.com/CrandellWS/79be3b8c9e8b74549af5

&#13;
&#13;
data = [{
    id: "A",
    text: "Hi From A",
    digit:12
}, {
    id: "B",
    text: "Hi From B",
    digit:8
}, {
    id: "C",
    text: "Hi From C",
    digit:15
}, {
    id: "D",
    text: "Hi From D",
    digit:42
}];

// I want to add the "text" values in my_data to the appropriate <divs>, which are the ones
// specified by the corresponding "id" in my_data.

// How can I write my d3 selector to use the "id" properties in my_data, without knowing
// what values my_data will contain? (I.e., I don't want to hardcode them!) 
// I'm using a dynamic data source, and my_data will frequently be
// changing. I'd like to add the "text" property to the appropriate <div> using d3. 
// It is guaranteed that the "id" properties in my_data will have a <div> with the same id
// already present in the DOM.



//From the tutorial at 
//http://bost.ocks.org/mike/bar/




//var data = [4, 8, 15, 16, 23, 42];

var x = d3.scale.linear()
    .domain([0, 4])
    .range([0, 42]);

d3.select(".chart")
  .selectAll("div")
    .data(data)
  .enter().append("div")

    .attr("id", function(d) {return d.id})
    .attr("name", function(d) {return d.id})
    .style("width", function(d) {return x(d.digit) + "px"; })
    .text(function(d) { return d.text; });




//From the tutorial at 
//http://bost.ocks.org/mike/bar/




//var data = [4, 8, 15, 16, 23, 42];

var x = d3.scale.linear()
    .domain([0, 4])
    .range([0, 42]);

d3.select(".chart")
  .selectAll("div")
    .data(data)
  .enter().append("div")

    .attr("id", function(d) {return d.id})
    .attr("name", function(d) {return d.id})
    .style("width", function(d) {return x(d.digit) + "px"; })
    .text(function(d) { return d.text; });


 
  function getObjByValue(myRoot, myType, myVal, newText){
    var d;
    console.log(typeof myRoot)
    if(typeof myRoot == "object"){
      for(d in myRoot){
        console.log(myRoot[d][myType])
        if(myRoot[d][myType] == myVal){
          d3.select('#'+myVal).text([newText]);
        }
      }
    }
  } 

getObjByValue(data, 'id', 'B', 'Now I want to B');
&#13;
#A {
    background-color: steelblue;
}
#B {
    background-color: red;
}
#C {
    background-color: green;
}
#D {
    background-color: orange;
}
#oldA {
    background-color: steelblue;
}
#oldB {
    background-color: red;
}
#oldC {
    background-color: green;
}
#oldD {
    background-color: orange;
}


.chart div {
  font: 10px sans-serif;
  background-color: steelblue;
  text-align: right;
  padding: 3px;
  margin: 1px;
  color: white;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="oldA" class="my_div">
    <p>Hi From A</p>
</div>
<div id="oldB" class="my_div">
    <p>Hi From B</p>
</div>
<div id="oldC" class="my_div">
    <p>Hi From C</p>
</div>
<div id="oldD" class="my_div">
    <p>Hi From D</p>
</div>

<br>
I want this text in B

<div class="chart"></div>
&#13;
&#13;
&#13;