d3.js在html表中嵌套数据更新线图

时间:2019-02-28 22:56:28

标签: javascript d3.js

我正在尝试使用d3创建仪表板。我正在把子弹图和迷你图放在桌子上。我已经能够毫无困难地放置项目符号图,但是我无法获得折线图的路径。我的数据是嵌套的,下面的内容正确地附加了svg和路径,但是路径为空。我尝试了多种更新模式,但看不到为什么无法通过以下路径获取任何数据。

任何帮助或建议,我们感激不尽。谢谢。

data = [{data:{data1:[{index:1, value:5},{index:2, value:9}]}}]
    
    
sparkScaleY = d3.scaleLinear()
  .domain([0,10])
  .range([10,0])
sparkScaleX = d3.scaleLinear()
  .domain([0,10])
  .range([0,15])
    
line = d3.line()
  .x(function(d) { return sparkScaleX (d.index); })
  .y(function(d) { return sparkScaleY (d.value); });
    
rows = d3.select("tbody")
 .selectAll("tr")
 .data(data)
 .enter()
 .append("tr")
    
spark = rows.append('td')
 .append('svg')
 .attr("class", "spark-svg")
 .attr("width", 15)
 .attr("height", 10)
 .append('path')
    
spark
  .attr("class", "spark-path")
    
function update(data){
    
  sparkSvg = d3.selectAll(".spark-svg")
     .data(data)
    
  sparkPath = sparkSvg.selectAll('.spark-path')
     .data(function(d){return [d.data.data1]})
     .enter()
     .append('path')
     .classed("new", true)
    
  sparkPath.attr('d', line)

  sparkPath
     .attr('d', line)
     .classed("new",false)
      
  sparkPath.exit().remove()

}
update(data)
<table>
<tbody>
</tbody>
</table>
<script src="https://d3js.org/d3.v5.min.js">

为澄清起见,更新之间的行数,列数,svg和路径数保持不变。

1 个答案:

答案 0 :(得分:2)

如果表结构是恒定的(行,列,svgs和迷你图(路径)的数量相同),那么我们可以稍微简化一下代码。在您的示例中,您正在更新,输入和退出更新功能。如果在创建表后不进入或退出任何内容,则无需执行此操作。

您已经在更新功能之前添加了行,列,svg和路径,因此我们在更新功能中所需的只是一个更新选择-让我们简化一点:

// Add rows once, same as before:
rows = d3.select("tbody")
  .selectAll("tr")
  .data(data)
  .enter()
  .append("tr")

// Add sparkline cell,svg, and path once, same as before:
var spark = rows.append('td')
  .append('svg')
  .attr("class", "spark-svg")
  .attr("width", 15)
  .attr("height", 10)
  .append('path')
  .attr("class", "spark-path")

// Only update, no need for entering/exiting if table structure doesn't change, only data:
function update(data){
  spark // use existing selection
    .data(data)  // assign new data
    .attr('d', function(d) {
      return line(d.data.data1);  // draw new data
  })
}

这看起来像:

data = [{data:{data1:[{index:1, value:5},{index:4, value:9},{index:7,value:4},{index:10,value:8}]}}]

sparkScaleY = d3.scaleLinear()
  .domain([0,10])
  .range([10,0])
sparkScaleX = d3.scaleLinear()
  .domain([0,10])
  .range([0,15])

line = d3.line()
  .x(function(d) { return sparkScaleX (d.index); })
  .y(function(d) { return sparkScaleY (d.value); });

// Add rows once:
rows = d3.select("tbody")
  .selectAll("tr")
  .data(data)
  .enter()
  .append("tr")

// Add title cell:
rows.append("td")
  .text(function(d) { 
    return Object.keys(d.data)[0];
  })

// Add sparkline cell,svg, and path once:
var spark = rows.append('td')
  .append('svg')
  .attr("class", "spark-svg")
  .attr("width", 15)
  .attr("height", 10)
  .append('path')
  .attr("class", "spark-path")

// Only update, no need for entering/exiting if table structure doesn't change, only data:
function update(data){

  spark // use the existing selection
    .data(data)
    .attr('d', function(d) {
      return line(d.data.data1);
  })
}
update(data)
path {
  stroke-width: 2;
  stroke:black;
  fill: none;
}
<script src="https://d3js.org/d3.v5.min.js"></script><table>
<tbody>
</tbody>
</table>

还有一些动态数据

var data = generate();

sparkScaleY = d3.scaleLinear()
  .domain([0,10])
  .range([10,0])
sparkScaleX = d3.scaleLinear()
  .domain([0,10])
  .range([0,15])

line = d3.line()
  .x(function(d) { return sparkScaleX (d.index); })
  .y(function(d) { return sparkScaleY (d.value); });

// Add rows once:
rows = d3.select("tbody")
  .selectAll("tr")
  .data(data)
  .enter()
  .append("tr")

// Add title cell:
rows.append("td")
  .text(function(d) { 
    return d.name;
  })

// Add sparkline cell,svg, and path once:
var spark = rows.append('td')
  .append('svg')
  .attr("class", "spark-svg")
  .attr("width", 15)
  .attr("height", 10)
  .append('path')
  .attr("class", "spark-path")

var spark2 = rows.append('td')
  .append('svg')
  .attr("class", "spark-svg")
  .attr("width", 15)
  .attr("height", 10)
  .append('path')
  .attr("class", "spark-path2")
  .style("stroke","steelblue");

// Only update, no need for entering/exiting if table structure doesn't change, only data:
function update(data){

  spark
    .data(data)
    .transition()
    .attr('d', function(d) {
      return line(d.spark1);
  })
  spark2
    .data(data)
    .transition()
    .attr('d', function(d) {
      return line(d.spark2);
  })
  
}

update(generate());
d3.interval(function(elapsed) {
   update(generate());
}, 2000);



function generate() { 
  return d3.range(10).map(function(d) {
    return {
      name: "row"+d,
      spark1: d3.range(10).map(function(d) {
        return {index: d, value: Math.random()*10}
      }),   
      spark2: d3.range(10).map(function(d) {
        return {index: d, value: Math.random()*10}
      })       
    }
  })
}
path {
  stroke-width: 2;
  stroke:black;
  fill: none;
}
<script src="https://d3js.org/d3.v5.min.js"></script><table>
<tbody>
</tbody>
</table>