javascript - Smooth transition on updating paths in d3 v5 - Stack Overflow

I'm trying to build a d3 line chart which updates the chart data on each click.Here's my pro

I'm trying to build a d3 line chart which updates the chart data on each click. Here's my progress so far:

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=".v5.min.js"></script>
<button id="translate">Translate</button>
<svg width="960" height="500"></svg>

I'm trying to build a d3 line chart which updates the chart data on each click. Here's my progress so far:

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/d3.v5.min.js"></script>
<button id="translate">Translate</button>
<svg width="960" height="500"></svg>

Currently, the chart updates instantly without any transition (even though i have added transition in update function). Whats am i doing wrong here?

I want to achieve something like this https://bl.ocks/mbostock/1642874, but on "click" rather than on "start" event.

Share Improve this question edited May 3, 2018 at 15:37 D_S_X asked May 3, 2018 at 15:19 D_S_XD_S_X 1,5697 gold badges18 silver badges38 bronze badges
Add a ment  | 

1 Answer 1

Reset to default 7

You aren't transitioning anything:

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

This doesn't specify that you are transitioning anything. The first two lines return the selection, the second two lines return a transition - you need to use .attr() on a transition to actually transition something. If .attr() is used on a selection, it simply updates that attribute. So, you need to use this pattern:

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

Or:

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

Also, you don't need to transition twice, add the new data and then shift the graph:

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

Snippet:

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/d3.v5.min.js"></script>
   <button id="translate">Translate</button>
<svg width="960" height="500"></svg>

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744658372a4586309.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信
['keyword'] : $thread['subject']; $header['description'] = $thread['description'] ? $thread['description'] : $thread['brief']; $_SESSION['fid'] = $fid; if ($ajax) { empty($conf['api_on']) and message(0, lang('closed')); $apilist['header'] = $header; $apilist['extra'] = $extra; $apilist['access'] = $access; $apilist['thread'] = well_thread_safe_info($thread); $apilist['thread_data'] = $data; $apilist['forum'] = $forum; $apilist['imagelist'] = $imagelist; $apilist['filelist'] = $thread['filelist']; $apilist['threadlist'] = $threadlist; message(0, $apilist); } else { include _include(theme_load('single_page', $fid)); } break; default: message(-1, lang('data_malformation')); break; } ?>