点击的d3.js第一次不起作用

时间:2018-03-14 11:55:32

标签: javascript d3.js

我正在尝试通过从输入中获取数据来制作d3饼图。点击功能在第一次单击时无需转换即可工作。 当我第一次单击按钮饼图更新时,但没有过渡。下次它正常工作。

var input = document.querySelectorAll(".input-block__item")
var data = [input[0].value, input[1].value, input[2].value, input[3].value] 
var width = 560,
    height = 500,
    radius = Math.min(width, height) / 2;      

var color = d3.scaleOrdinal(d3.schemeAccent)

var arc = d3.arc()
    .outerRadius(radius - 10)
    .innerRadius(0);

var pie = d3.pie()
    .sort(null)
    .value(function(d,i) { return d; });
var svg = d3.select(".pie-block").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
var block = svg.selectAll(".arc")
    .data(pie(data))
    .enter().append("g")
    .attr("class", "arc")
block.append("path")
    .attr("d", arc)
    .style("fill", function(d) { return color(d.data); }); 
block.data(pie(data))
    .transition()
    .duration(1000)
    .ease(d3.easeLinear)
    .attrTween("d", arc2Tween);
//update

function arc2Tween(d) {
    var interp = d3.interpolate(this._current, d);   
    this._current = d;                    
    return function(t) {               
      var tmp = interp(t);                
      return arc(tmp);      
    }
  };
d3.select(".mybtn")
                .on("click", function update() {
          var data = [input[0].value, input[1].value, input[2].value, input[3].value]
          block.select("path")
            .data(pie(data))
            .transition()
            .duration(1000)
            .ease(d3.easeLinear)
            .attrTween("d", arc2Tween);
});
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<a href="#" class="mybtn">Show</a>
<div class="container">
  <div class="input-block">
    <input type="text" value="1" class="input-block__item input-block__item--1">
    <input type="text" value="2" class="input-block__item input-block__item--2">
    <input type="text" value="3" class="input-block__item input-block__item--3">
    <input type="text" value="4" class="input-block__item input-block__item--4">
  </div>
  <div class="pie-block">

  </div>
</div>

1 个答案:

答案 0 :(得分:0)

pen in CodePen应显示按预期工作的转换。说实话,我没有一个伟大的最佳实践来到这里。我只是注意到在原始代码片段中,数据绑定似乎在第一次按键单击时运行了两次:一次是原始数据,紧接着是新数据。

我尝试将更新逻辑分离到D3 general update pattern之后的函数。我的第一次尝试并没有真正起作用。我将var block移回外部范围,并将enter逻辑移回外部范围,然后它开始工作。

var input = document.querySelectorAll(".input-block__item");
var data = [input[0].value, input[1].value, input[2].value, input[3].value];
var width = 560,
    height = 500,
    radius = Math.min(width, height) / 2;

var color = d3.scaleOrdinal(d3.schemeAccent)

var arc = d3.arc()
    .outerRadius(radius - 10)
    .innerRadius(0);

var pie = d3.pie()
    .sort(null)
    .value(function(d,i) { return d; });

var svg = d3.select(".pie-block").append("svg")
    .attr("width", width)
    .attr("height", height)
    .append("g")
    .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

// join
var block = svg
    .selectAll(".arc")
    .data(pie(data));

// enter
block.enter()
    .append("g")
    .attr("class", "arc")
    .append("path")
    .attr("d", arc)
    .style("fill", function(d) { return color(d.data); });
// initial data update
update(data);

function arc2Tween(d) {
    var interp = d3.interpolate(this._current, d);
    this._current = d;
    return function(t) {
      var tmp = interp(t);
      return arc(tmp);
    }
  };

d3.select(".mybtn")
  .on("click", function () {
    update([input[0].value, input[1].value, input[2].value, input[3].value]);
});

function update(data) {
  // join
  block = svg
      .selectAll(".arc")
      .data(pie(data));

  // update
  block.select("path")
      .transition()
      .duration(1000)
      .ease(d3.easeLinear)
      .attrTween("d", arc2Tween);
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
<a href="#" class="mybtn">Show</a>
<div class="container">
  <div class="input-block">
    <input type="text" value="1" class="input-block__item input-block__item--1">
    <input type="text" value="2" class="input-block__item input-block__item--2">
    <input type="text" value="3" class="input-block__item input-block__item--3">
    <input type="text" value="4" class="input-block__item input-block__item--4">
  </div>
  <div class="pie-block">

  </div>
</div>