d3 on click on circle pause and resume transition

2019-07-09 02:44发布

I would like help to correct my code to click the marker circle element to pause or resume transition of this element along the line. My code moves marker along a line and I can pause and resume this transition using on click on button element but I would like to be able to click on the marker circle itself, not the button. I have used various references including : http://www.nytimes.com/interactive/2013/09/25/sports/americas-cup-course.html http://jsfiddle.net/meetamit/UJuWX/3/ http://jsfiddle.net/Y62Hq/2/ D3 tween - pause and resume controls

I would ultimately like to be able animate a marker along a geo path, pause and resume this at points along the path and click through on these points.

this is my code so far:

<!DOCTYPE html>
<html lang="en">
    <head>
<meta charset="utf-8">
<title>Need help</title>

<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script src="https://d3js.org/d3-queue.v3.min.js"></script>

<style type="text/css">

body{
    font-family:"Helvetica Neue", Helvetica, sans-serif;
    color: red;
}
button {
  position: absolute;
  top: 15px;
  left: 10px;
  background: #004276;
  padding-right: 26px;
  border-radius: 2px;
  cursor: pointer;
}
circle {
  fill: steelblue;
  stroke: pink;
  stroke-width: 3px;
}
.point{
    fill:green;

}
.line{
  fill: none;
  stroke: red;
  stroke-width: 4;
  stroke-dasharray: 4px,8px;
}
</style>
</head>
<body>

<button>Start</button>

<script>

    var w = 960,
        h = 500;

    var duration = 10000;

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

    var line = d3.line()
    .x(function(d){return (d)[0];})
    .y(function(d){return (d)[1];});

var data =
 [
  [480, 200],
  [580, 400],
  [680, 100],
  [780, 300],
  [180, 300],
  [280, 100],
  [380, 400]
];

//path to animate
var linepath = svg.append("path")
  .data([data])
  .attr("d", line)
    .attr('class', 'line')
    .attr("d", function(d){
        console.log(this);
        return line(d)
    });

var points = svg.selectAll("circle")
      .data(data)
        .enter()
        .append("circle")
      .attr("r", 7)
        .attr("transform", function(d) { return "translate(" + (d) + ")"; })
        .attr("class", "point");

var pauseValues = {
        lastTime: 0,
        currentTime: 0
        };
        var marker = svg.append("circle")
          .attr("r", 19)
          .attr("transform", "translate(" + (data[0]) + ")")
            .on('click', function(d,i){
                d3.select(this)
                .style("fill", "orange")
                .transition()
            });

function transition() {
  marker.transition()
        .duration(duration - (duration * pauseValues.lastTime))
        .attrTween("transform", translateAlong(linepath.node()))
        .on("end", function(){
        pauseValues = {
          lastT: 0,
          currentT: 0
        };
        transition()
      });
}

function translateAlong(path) {
  var l = path.getTotalLength();
  return function(d, i, a) {
    return function(t) {
      t += pauseValues.lastTime;
      var p = path.getPointAtLength(t * l);
      pauseValues.currentTime = t;
      return "translate(" + p.x + "," + p.y + ")";
    };
  };
}

d3.select('button').on('click',function(d,i){
  var self = d3.select(this);
  if (self.text() == "Pause"){
        self.text('Start');
        marker.transition()
      .duration(0);
        setTimeout(function(){
            pauseValues.lastTime = pauseValues.currentTime;
        }, 100);
  }else{
    self.text('Pause');
    transition();
  }
});

</script>
</body>
</html>

标签: d3.js svg
1条回答
来,给爷笑一个
2楼-- · 2019-07-09 03:19

To check if the circle is moving in the click function use d3.active(), which...

... returns null if there is no such active transition on the specified node.

Like this:

.on('click', function(d, i) {
    if (d3.active(this)) {
        marker.transition();
        setTimeout(function() {
            pauseValues.lastTime = pauseValues.currentTime;
        }, 100);
    } else {
        transition();
    }
});

Here is your code with that change:

<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script src="https://d3js.org/d3-queue.v3.min.js"></script>

<style type="text/css">
  body {
    font-family: "Helvetica Neue", Helvetica, sans-serif;
    color: red;
  }
  
  button {
    position: absolute;
    top: 15px;
    left: 10px;
    background: #004276;
    padding-right: 26px;
    border-radius: 2px;
    cursor: pointer;
  }
  
  circle {
    fill: steelblue;
    stroke: pink;
    stroke-width: 3px;
  }
  
  .point {
    fill: green;
  }
  
  .line {
    fill: none;
    stroke: red;
    stroke-width: 4;
    stroke-dasharray: 4px, 8px;
  }

</style>

<body>

  <button>Start</button>

  <script>
    var w = 960,
      h = 500;

    var duration = 10000;

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

    var line = d3.line()
      .x(function(d) {
        return (d)[0];
      })
      .y(function(d) {
        return (d)[1];
      });

    var data = [
      [480, 200],
      [580, 400],
      [680, 100],
      [780, 300],
      [180, 300],
      [280, 100],
      [380, 400]
    ];

    //path to animate
    var linepath = svg.append("path")
      .data([data])
      .attr("d", line)
      .attr('class', 'line')
      .attr("d", function(d) {
        return line(d)
      });

    var points = svg.selectAll("circle")
      .data(data)
      .enter()
      .append("circle")
      .attr("r", 7)
      .attr("transform", function(d) {
        return "translate(" + (d) + ")";
      })
      .attr("class", "point");

    var pauseValues = {
      lastTime: 0,
      currentTime: 0
    };
    var marker = svg.append("circle")
      .attr("r", 19)
      .attr("transform", "translate(" + (data[0]) + ")")
      .on('click', function(d, i) {
        if (d3.active(this)) {
          marker.transition();
          setTimeout(function() {
            pauseValues.lastTime = pauseValues.currentTime;
          }, 100);
        } else {
          transition();
        }
      });

    function transition() {
      marker.transition()
        .duration(duration - (duration * pauseValues.lastTime))
        .attrTween("transform", translateAlong(linepath.node()))
        .on("end", function() {
          pauseValues = {
            lastT: 0,
            currentT: 0
          };
          transition()
        });
    }

    function translateAlong(path) {
      var l = path.getTotalLength();
      return function(d, i, a) {
        return function(t) {
          t += pauseValues.lastTime;
          var p = path.getPointAtLength(t * l);
          pauseValues.currentTime = t;
          return "translate(" + p.x + "," + p.y + ")";
        };
      };
    }

    d3.select('button').on('click', function(d, i) {
      var self = d3.select(this);
      if (self.text() == "Pause") {
        self.text('Start');
        marker.transition()
          .duration(0);
        setTimeout(function() {
          pauseValues.lastTime = pauseValues.currentTime;
        }, 100);
      } else {
        self.text('Pause');
        transition();
      }
    });

  </script>
</body>

查看更多
登录 后发表回答