【问题标题】:D3 stop and restart transition along path to allow click through to geo data coordinatesD3 沿路径停止并重新开始过渡,以允许点击地理数据坐标
【发布时间】:2018-05-15 05:32:36
【问题描述】:

您好,我正在尝试使用 D3 来暂停和恢复标记沿此示例D3 tween - pause and resume controls 的路径的转换,并在此D3 transition along segments of path and pause at coordinate values 等特定数据点上停止标记的转换。我通过单击标记开始过渡,并希望能够停止它,然后在单击它时重新启动它——此时它会暂停一段时间然后开始。

我希望能够完全停止标记,这样我就可以对该点执行某些操作,即根据其 json 数据单击特定单击点的 xlink:href,然后离开页面 - 然后返回标记过渡并从它停止的同一点恢复过渡。

我想我需要将 pauseValues 传递给转换函数,但就是不明白该怎么做。

这是我的代码:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">

  <script src="https://d3js.org/d3.v4.min.js"></script>

<style type="text/css">
  body {
    font-family: "Helvetica Neue", Helvetica, sans-serif;
    color: red;
  }


  circle {
    fill: steelblue;
    stroke: steelblue;
    stroke-width: 3px;
  }

  .point {
    fill: green;
  }

  .line {
    fill: none;
    stroke: red;
    stroke-width: 4;
    stroke-dasharray: 4px, 8px;
  }

</style>

<body>

  <script>
    var width = 960,
      height = 500;

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

    var duration = 20000/data.length,
        pauseTime = 2000;

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

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

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

    //Want to activate circles when marker paused on them - intention is to have on click to href and stop marker while href is displayed
    svg.selectAll("circle")
        .data(data)
        .enter()
        .append("circle")
        .attr("class", "point")
        .attr("r", 10)

        .attr("transform", function(d) {
            return "translate(" + d + ")";
      })

        .on('click', function(d, i) {
            d3.select(this)
              .style("fill", "pink")
              //sample - data will be for each point and based on the geojson in real example
              .append("a")
            .attr("xlink:href", "http://collections.anmm.gov.au/en/objects/details/11429/")

            pausePoints.push(i);
            console.log("pausePoints_push_i: " +pausePoints.push(i));
            console.log("pausePoints: " + pausePoints);
            if (pausePoints.length === 1)
            transition();    
        });


    var marker = svg.append("circle")
      .attr("r", 19)
      .attr("transform", "translate(" + (data[0]) + ")")
            .on('click', function(d, i) {
            d3.select(this)
              .style("fill", "pink")

                pausePoints.push(i);

                if (pausePoints.length === 1)
                setTimeout(function() {
                pauseValues.lastTime = pauseValues.currentTime;
              }, 100);
        transition();    
        });


    var pauseValues = {
      lastTime: 0,
      currentTime: 0
    };

    var pausePoints = [],
        iter = 0,
        transData = data.slice();

    function transition() {
      marker.transition()
        .ease(d3.easeLinear)
       .duration(duration - (duration * pauseValues.lastTime))
        .attrTween("transform", function(){
          var p0 = transData.shift(),
              p1 = transData[0];
              m = (p0[1] - p1[1]) / (p0[0] - p1[0]),
              b = p0[1] - (m * p0[0]),
              i = d3.interpolateNumber(p0[0], p1[0]);

            return function(t){
            //console.log("T: " +t);
              var x = i(t),
                  y = m*x + b;

              return "translate(" + x + "," + y + ")";
            }
        })
        .on("end", function(){
          if (transData.length <= 1) return;
          iter++;    
          setTimeout(transition, pausePoints.indexOf(iter) !== -1 ? pauseTime : 0);

        });
    };

  </script>
</body>

【问题讨论】:

    标签: javascript d3.js transition geojson


    【解决方案1】:

    我帮助你解决了你的最后一个问题。从我写的代码中,你引入了这个变量pauseValues,它的作用是什么?据我所知,它会尝试根据之前的暂停来调整持续时间;只有在所有路径上运行一个长过渡时才需要这个。我的代码将每条腿作为一个单独的过渡运行。如果你想暂停和恢复点击这里是一个简单的重构:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
      <meta charset="utf-8">
    
      <script src="https://d3js.org/d3.v4.min.js"></script>
    
      <style type="text/css">
        body {
          font-family: "Helvetica Neue", Helvetica, sans-serif;
          color: red;
        }
        
        circle {
          fill: steelblue;
          stroke: steelblue;
          stroke-width: 3px;
        }
        
        .point {
          fill: green;
        }
        
        .line {
          fill: none;
          stroke: red;
          stroke-width: 4;
          stroke-dasharray: 4px, 8px;
        }
      </style>
    
      <body>
    
        <script>
          var width = 960,
            height = 500;
    
          var data = [
            [610.4199794444444, 243.7191682432953], //Paris
            [480, 200],
            [580, 400],
            [680, 100],
            [780, 300],
            [180, 300],
            [280, 100],
            [380, 400]
          ];
    
          var duration = 20000 / data.length,
            pauseTime = 2000;
    
          var line = d3.line()
            .x(function(d) {
              return (d)[0];
            })
            .y(function(d) {
              return (d)[1];
            });
    
          var svg = d3.select("body")
            .append("svg")
            .attr("width", width)
            .attr("height", height);
    
          //path to animate - marker transitions along this path
          var path = svg.append("path")
            .data([data])
            .attr("d", line)
            .attr('class', 'line')
            .attr("d", function(d) {
              return line(d)
            });
    
          //Want to activate circles when marker paused on them - intention is to have on click to href and stop marker while href is displayed
          svg.selectAll("circle")
            .data(data)
            .enter()
            .append("circle")
            .attr("class", "point")
            .attr("r", 10)
    
          .attr("transform", function(d) {
            return "translate(" + d + ")";
          })
    
          .on('click', function(d, i) {
            d3.select(this)
              .style("fill", "pink")
              //sample - data will be for each point and based on the geojson in real example
              .append("a")
              .attr("xlink:href", "http://collections.anmm.gov.au/en/objects/details/11429/")
    
            pausePoints.push(i);
    
            if (pausePoints.length === 1)
              transition();
          });
    
    
          var marker = svg.append("circle")
            .attr("r", 19)
            .attr("transform", "translate(" + (data[0]) + ")")
            .on('click', function(d, i) {
                transition();
            });
    
          var pausePoints = [],
            iter = 0;
            transData = data.slice();
    
          function transition() {
            marker.transition()
              .ease(d3.easeLinear)
              .duration(duration)
              .attrTween("transform", function() {
                var p0 = transData.shift(),
                  p1 = transData[0],
                  m = (p0[1] - p1[1]) / (p0[0] - p1[0]),
                  b = p0[1] - (m * p0[0]),
                  interp = d3.interpolateNumber(p0[0], p1[0]);
    
                return function(t) {
    
                  var x = interp(t),
                    y = m * x + b;
    
                  return "translate(" + x + "," + y + ")";
                }
              })
              .on("end", function() {
                iter++;
                if (
                  transData.length <= 1 || // out of points
                  pausePoints.indexOf(iter) !== -1) // on a clicked point
                {
                  return;
                }
                transition();
              });
          };
        </script>
      </body>

    【讨论】:

    • 是的,非常感谢,我现在了解发生的事情要好一些,您所写的内容对我很有帮助。我希望能够开始和停止点上的过渡,并通过单击我现在可以执行的标记重新开始。我稍微更改了您的代码以添加“pausePoints.push(i);”到点击标记功能,我得到了我希望的结果。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 2018-05-01
    • 1970-01-01
    • 2018-07-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多