【问题标题】:Smooth transition on updating paths in d3 v5在 d3 v5 中更新路径的平滑过渡
【发布时间】:2018-05-03 15:19:45
【问题描述】:

我正在尝试构建一个 d3 折线图,它会在每次点击时更新图表数据。 这是我到目前为止的进展:

var n = 10,
  random = d3.randomNormal(0, .2),
  data = d3.range(n).map(random);

var svg = d3.select("svg"),
  margin = {
    top: 20,
    right: 20,
    bottom: 20,
    left: 40
  },
  width = +svg.attr("width") - margin.left - margin.right,
  height = +svg.attr("height") - margin.top - margin.bottom,
  g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleLinear()
  .domain([0, n - 1])
  .range([0, width]);

var y = d3.scaleLinear()
  .domain([-1, 1])
  .range([height, 0]);

var line = d3.line()
  .x(function(d, i) {
    return x(i);
  })
  .y(function(d, i) {
    return y(d);
  });

g.append("defs").append("clipPath")
  .attr("id", "clip")
  .append("rect")
  .attr("width", width)
  .attr("height", height);

g.append("g")
  .attr("class", "axis axis--x")
  .attr("transform", "translate(0," + y(0) + ")")
  .call(d3.axisBottom(x));

g.append("g")
  .attr("class", "axis axis--y")
  .call(d3.axisLeft(y));

g.append("g")
  .attr("clip-path", "url(#clip)")
  .append("path")
  .datum(data)
  .attr("class", "line")
  .attr('d', line)

function tick() {

  // Push a new data point onto the back.
  data.push(random());

  // Redraw the line.
  d3.select(".line")
    .attr("d", line)
    .attr("transform", null)
    .transition()
    .duration(300)

  // Slide it to the left.
  d3.select(".line")
    .attr("transform", "translate(" + x(-1) + ",0)")
    .transition()
    .duration(300)

  // Pop the old data point off the front.
  data.shift();

}

d3.select("#translate")
  .on("click", tick)
.line {
  fill: none;
  stroke: #000;
  stroke-width: 1.5px;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<button id="translate">Translate</button>
<svg width="960" height="500"></svg>

目前,图表会立即更新,没有任何过渡(即使我在更新功能中添加了过渡)。我在这里做错了什么?

我想实现类似https://bl.ocks.org/mbostock/1642874 的目标,但在“点击”而不是“开始”事件上。

【问题讨论】:

    标签: javascript jquery css d3.js


    【解决方案1】:

    你没有过渡任何东西:

    d3.select(".line")
      .attr("...")
      .transition()
      .duration()
    

    这并不表示您正在转换任何内容。前两行返回选择,后两行返回转换 - 您需要在转换上使用 .attr() 才能实际转换某些内容。如果 .attr() 用于选择,它只会更新该属性。所以,你需要使用这个模式:

    d3.select(".line")
      .transition()
      .duration()
      .attr("...")  // attribute to be transitioned
    

    或者:

    d3.select(".line")
      .transition()
      .attr("...")  // attribute to be transitioned
      .duration()
    

    另外,您不需要转换两次,添加新数据然后移动图表:

    // Redraw the line.
    d3.select(".line")
      .attr("d", line)
      .attr("transform", null)
      .transition()
      .attr("transform", "translate(" + x(-1) + ",0)")
      .duration(300)
    

    片段:

    var n = 10,
                random = d3.randomNormal(0, .2),
                data = d3.range(n).map(random);
    
            var svg = d3.select("svg"),
                margin = {
                    top: 20,
                    right: 20,
                    bottom: 20,
                    left: 40
                },
                width = +svg.attr("width") - margin.left - margin.right,
                height = +svg.attr("height") - margin.top - margin.bottom,
                g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
    
            var x = d3.scaleLinear()
                .domain([0, n - 1])
                .range([0, width]);
    
            var y = d3.scaleLinear()
                .domain([-1, 1])
                .range([height, 0]);
    
            var line = d3.line()
                .x(function(d, i) {
                    return x(i);
                })
                .y(function(d, i) {
                    return y(d);
                });
    
            g.append("defs").append("clipPath")
                .attr("id", "clip")
                .append("rect")
                .attr("width", width)
                .attr("height", height);
    
            g.append("g")
                .attr("class", "axis axis--x")
                .attr("transform", "translate(0," + y(0) + ")")
                .call(d3.axisBottom(x));
    
            g.append("g")
                .attr("class", "axis axis--y")
                .call(d3.axisLeft(y));
    
            g.append("g")
                .attr("clip-path", "url(#clip)")
                .append("path")
                .datum(data)
                .attr("class", "line")
                .attr('d', line)
    
            function tick() {
    
                // Push a new data point onto the back.
                data.push(random());
    
                // Redraw the line.
                d3.select(".line")
                    .attr("d", line)
                    .attr("transform", null)
    				.transition()
                    .attr("transform", "translate(" + x(-1) + ",0)")
                    .duration(300)
    				
                // Pop the old data point off the front.
                data.shift();
    
            }
    
            d3.select("#translate")
                .on("click", tick)
    .line {
                fill: none;
                stroke: #000;
                stroke-width: 1.5px;
            }
    <script src="https://d3js.org/d3.v5.min.js"></script>
       <button id="translate">Translate</button>
    <svg width="960" height="500"></svg>

    【讨论】:

      猜你喜欢
      • 2018-07-14
      • 2018-02-17
      • 2018-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多