D3沿路径停止并重新启动过渡,以允许单击进入地理数据坐标 [英] D3 stop and restart transition along path to allow click through to geo data coordinates

查看:65
本文介绍了D3沿路径停止并重新启动过渡,以允许单击进入地理数据坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用D3暂停和恢复沿此示例所示路径的标记的过渡 D3沿路径段过渡,并在坐标值处暂停.我通过单击标记来开始转换,并且希望能够停止它,然后在单击它时重新启动它-此时它会暂停一段时间然后再启动.

Hi I’m trying to use D3 to pause and resume a transition of a marker along a path like this example D3 tween - pause and resume controls plus stop the marker's transition on a particular data point like this D3 transition along segments of path and pause at coordinate values. I am starting the transition by clicking on the marker and would like to be able to stop it and then restart it when it is clicked – at the moment it pauses for a period and then starts.

我希望能够完全停止标记,因此我可以处理该点,即根据其json数据单击特定链接的点的xlink:href,然后离开页面-然后返回标记过渡,并从停止的同一点恢复过渡.

I’d like to be able to stop the marker completely so I can do something with the point ie click through to xlink:href for a particular clicked point based on its json data and so leave the page - and then return to the marker transition and resume the transition from the same point it stopped.

我认为我需要将pauseValues传递到转换函数中,但根本不了解如何执行此操作.

I think I need to pass the pauseValues into the transition function but just can’t understand how to do this.

这是我的代码:

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

推荐答案

我为您解决了最后一个问题.从我编写的代码中,您引入了此变量pauseValues,它打算做什么?据我所知,它尝试根据先前的暂停来调整持续时间;只有在所有路径上进行长时间过渡时,才需要此功能.我的代码将每个分支作为单个过渡运行.如果您想暂停并继续点击,这里有一个简单的重构方法:

I helped you with your last question. From the code I wrote, you introduced this variable pauseValues, what is it intended to do? From what I can tell, it attempts to adjust the duration based on previous pauses; you only needed this when you were running one long transition across all the paths. My code runs each leg as a single transition. If you want to pause and resume on click here's a simple refactor:

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

这篇关于D3沿路径停止并重新启动过渡,以允许单击进入地理数据坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆