如何根据键盘输入使圆圈消失?

How to make the circles disappear based on keyboard input?

基于这个例子:http://bl.ocks.org/d3noob/10633704 我想在我的键盘上输入一个数字(一个数字)并在 array.slice() 的帮助下使圆圈消失。不幸的是,它并没有很好地工作。在我的代码中,我根据数组 days 的值创建了一些圆圈。使用 HTML 部分,我可以创建一个按钮,我可以在其中输入数字。对于最后一部分 days.slice(nValue) 我希望输入的数字与 slice() 函数括号内的数字相同,因此数组 days 越来越短并自动让圆圈基于数组的值消失。但不幸的是,我在这段代码中犯了一个错误。有人可能会如此友善并提供帮助吗?我正在使用 D3 来解决这个问题。 谢谢

<!DOCTYPE html>
<meta charset="utf-8">
<title>Input (number) test</title>

<p>
  <label for="nValue" 
         style="display: inline-block; width: 120px; text-align: right">
         angle = <span id="nValue-value"></span>
  </label>


  <input type="number" min="0" max="360" step="4" value="0" id="nValue">
</p>

<script src="http://d3js.org/d3.v3.min.js"></script>
<script>

var width = 600;
var height = 300;

var svg = d3.select("body")
      .append("svg")
      .attr("width", width)    
      .attr("height", height); 



  var days = [7, 12, 20, 31, 40, 50];
  console.log(days);




  var circle = svg.selectAll("circle")
            .data(days)
            .enter().append("circle")
            .attr("cy", 60)
            .attr("cx", function(d, i) { return i * 100 + 40; })
            .attr("r", function(d) { return Math.sqrt(d); });



  d3.select("#nValue").on("input", function() {
  update(+this.value);
});


// Initial update value 
update(0);




function update(nValue) {

days.slice(nValue);
}

尝试将您的更新函数更改为:

function update(nValue) {

 days = days.slice(nValue);

}

我花了一段时间才明白你在这里的目的,我的理解可能还有点偏差。

问题

据我所知,您正在修改数据数组(在本例中使用 select 菜单),但修改后的数组似乎并未修改您的可视化。本质上,如 "the array days is getting shorter ... let circles based on the value[s] of the array disappear."

更新可视化

要更新可视化,您需要将新数据绑定到您的 selection。在此之后,您可以删除可视化中不需要的元素、添加新元素(与此问题无关)或修改现有元素。单独更改数据数组不会更新可视化。要让可视化利用新信息,您需要将该数据绑定到 selection:

circle.data(data);

然后您可以删除旧项目:

circle.exit().remove();

然后你可以修改旧项目的属性:

circle.attr('cx',function(d,i) {...

您的更新函数至少需要更新数据并删除不需要的元素。

更改数组

在下面的代码片段中,我根据数组中的数据附加了一个 select 菜单和带有 d3 的圆圈。选择菜单中的项目将删除一个圆圈:

var data = [10,20,30,40,50,60,70,80,90,100];

var color = d3.schemeCategory10; // color array built in

//// Add the select and options:
var select = d3.select('body')
  .append('select')
  .on('change',function() { update(this.value) });
  
var start = select.append('option')
  .html("select: ");
  
var options = select.selectAll('.option')
  .data(data)
  .enter()
  .append('option')
  .attr('class','option')
  .attr('value',function(d,i) { return i; })
  .html(function(d) { return d; });


  
//// Add the circles (and svg)
var svg = d3.selectAll('body')
  .append('svg')
  .attr('width',500)
  .attr('height',200);
  
var circles = svg.selectAll('circle')
  .data(data)
  .enter()
  .append('circle')
  .attr('cx',function(d,i) { return i * 30 + 50; })
  .attr('cy',50)
  .attr('r',10)
  .attr('fill',function(d,i) { return color[i]; });
  
  
// Update everything:
function update(i) {
  data.splice(i,1); // remove that element.
  
  // Update and remove option from the select menu:
  options.data(data).exit().remove();
  
  // Remove that circle:
  circles.data(data).exit().remove(); 
  
  circles.attr('cx',function(d,i) { return i * 30 + 50; })
    .attr('fill',function(d,i) { return color[i]; });
  
  // reset the select menu:
  start.property('selected','selected');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>

这里有个问题,每次只去掉最后一个圆圈和菜单项。为什么?想象一个四元素数组,如果你删除了第二项,d3 不知道你删除了第二项,你可能修改了元素二和三并删除了元素四。

由于您的所有项目都附加了它们的增量(它们在数组中的位置),并且这不考虑删除其他项目时产生的空洞,您需要稍微改变一下方法。

一个解决方案

而不是依赖数组中项目的增量(因为每次从数组中删除另一个元素之前的元素都会改变),您可以在您的数据。

这需要稍微重组您的数据。类似于:

var data = [ {id:1,value:1},{id2....

由于id 属性 不会改变,这使得属性 更好地设置属性。看看下面的片段:

var data = [{id:0,value:10},{id:1,value:20},{id:2,value:23},{id:3,value:40},{id:4,value:50},{id:5,value:60},{id:6,value:70},{id:7,value:77},{id:8,value:86},{id:9,value:90}];

var color = d3.schemeCategory10; // color array built in

//// Add the select and options:
var select = d3.select('body')
  .append('select')
  .on('change',function() { update(this.value); } ); // add an event listener for changes

// append a default value:
var start = select.append('option')
  .html("Select:");
  
var options = select.selectAll('.option')
  .data(data)
  .enter()
  .append('option')
  .attr('class','option')
  .attr('value',function(d,i) { return i; })
  .html(function(d) { return d.value; });
  
  
//// Add the circles (and svg)
var svg = d3.selectAll('body')
  .append('svg')
  .attr('width',500)
  .attr('height',200);
  
var circles = svg.selectAll('circle')
  .data(data)
  .enter()
  .append('circle')
  .attr('cx',function(d) { return d.id * 30 + 50; })
  .attr('cy',50)
  .attr('r',10)
  .attr('fill',function(d) { return color[d.id]; });
  
  
// Update everything:
function update(i) {
  data.splice(i,1); // remove the element selected
  
  // Update and remove option from the select menu:
  options.data(data).exit().remove();
  
  // Remove that circle:
  circles.data(data).exit().remove(); 
  
  // update the options (make sure each option has the correct attributes
  options.attr('value',function(d,i) { return i; })
  .html(function(d) { return d.value; })
  
  // Make sure circles are in the right place and have the right color:
  circles.attr('cx',function(d) { return d.id * 30 + 50; })
    .attr('fill',function(d) { return color[d.id]; });
    
  // reset the default value so the change will work on all entries:
  start.property('selected', 'selected');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>