代码之家  ›  专栏  ›  技术社区  ›  user3471259

d3单击圆圈暂停并恢复标记沿直线的过渡

  •  2
  • user3471259  · 技术社区  · 8 年前

    我想帮助更正我的代码,单击标记圆元素以暂停或恢复该元素沿直线的转换。我的代码沿着一条线移动标记,我可以使用点击按钮元素暂停并恢复此转换,但我希望能够点击标记圆本身,而不是按钮。我使用了各种参考资料,包括: 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

    我最终希望能够沿地理路径设置标记的动画,在路径上的点暂停并继续,然后单击这些点。

    这是我目前的代码:

    <!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>
    
    1 回复  |  直到 8 年前
        1
  •  2
  •   Gerardo Furtado    8 年前

    检查圆是否在 click 函数使用 d3.active() 哪一个

    ... 如果指定节点上没有此类活动转换,则返回null。

    这样地:

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

    以下是您的更改代码:

    <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>