我可以在拖动时更新正在进行的d3过渡

时间:2015-08-25 16:05:45

标签: d3.js

我使用d3将lat / lon点添加到地理投影上。我还实现了一些拖动控件来旋转球体。

我希望有一个按顺序添加点的转换,但是如果我在转换期间拖动球体移动它,事情就会出错:我认为它是因为转换端点在任何之前设置旋转发生 - 如果没有发生旋转,这些点似乎在它们之间的位置。

如果我在球体出现后旋转它们,它们会按照它们应该的位置(根据更新功能)。

有谁知道如何排序?你可以在延迟之后有效地进行追加,即在添加下一个点之前一次性添加和转换点。或者也许有一些方法可以更新ondrag函数中的转换。

我的示例代码位于jsfiddle here

leeroyjenkins = function(){
    var data = [{"lat": 0, "lon": 0},
                {"lat": 10, "lon": 10},
                {"lat": 20, "lon": 20},
                {"lat": 30, "lon": 30},
                {"lat": 40, "lon": 40},]
    main(data);
};

var main = function(points) {
  var width = 960,
      height = 500;

  var projection = d3.geo.orthographic()
      .scale(250)
      .translate([width / 2, height / 2])
      .clipAngle(90);

  var pointpath = function(d, r) {
              var pr = d3.geo.path().projection(projection).pointRadius(r);
              return pr({type: "Point", coordinates: [d.lon, d.lat]})
            }

  var λ = d3.scale.linear()
      .domain([0, width])
      .range([-180, 180]);

  var φ = d3.scale.linear()
      .domain([0, height])
      .range([90, -90]);

  var drag = d3.behavior.drag()
      .origin(function() { var r = projection.rotate();
                          return {x: λ.invert(r[0]), y: φ.invert(r[1])}; })
      .on("drag", function() {
        projection.rotate([λ(d3.event.x), φ(d3.event.y)]);
        svg.selectAll("path.point").attr("d", function(d) {return pointpath(d, 10)});
      });

  var tooltip = d3.select("body")
                  .append("div") 
                  .attr("id", "tooltip");

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

  svg.append("path")
        .attr("id", "outline")
        .datum({type: "Sphere"})
        .attr("d", d3.geo.path().projection(projection));

  var point = svg.selectAll("path.point").data(points);
  point.enter()
        .append("path")
          .attr("class", "point")
          .attr("d", function(d) {return pointpath(d, 0)})
            .transition()
            .delay(function(d, i){return i * 1000;})
            .duration(500)
            .attr("d", function(d) {return pointpath(d, 10)});
};

leeroyjenkins();

1 个答案:

答案 0 :(得分:0)

应使用解决方案here更新小提琴。基本上,我做了一个属性补间,并将插值半径设置为该数据点的属性 - 然后在更新函数中访问它。这看起来像是一种最佳解决方案吗?

leeroyjenkins = function(){
    var data = [{"lat": 0, "lon": 0},
                {"lat": 10, "lon": 10},
                {"lat": 20, "lon": 20},
                {"lat": 30, "lon": 30},
                {"lat": 40, "lon": 40},]
    main(data);
};

var main = function(points) {
  var width = 960,
      height = 500;

  var projection = d3.geo.orthographic()
      .scale(250)
      .translate([width / 2, height / 2])
      .clipAngle(90);

  var pointpath = function(d, r) {
              var pr = d3.geo.path().projection(projection).pointRadius(r);
              return pr({type: "Point", coordinates: [d.lon, d.lat]})
            }

  var λ = d3.scale.linear()
      .domain([0, width])
      .range([-180, 180]);

  var φ = d3.scale.linear()
      .domain([0, height])
      .range([90, -90]);

  var drag = d3.behavior.drag()
      .origin(function() { var r = projection.rotate();
                          return {x: λ.invert(r[0]), y: φ.invert(r[1])}; })
      .on("drag", function() {
        projection.rotate([λ(d3.event.x), φ(d3.event.y)]);
        svg.selectAll("path.point").attr("d", function(d) {return pointpath(d, d.r)});
      });

  var tooltip = d3.select("body")
                  .append("div") 
                  .attr("id", "tooltip");

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

  svg.append("path")
        .attr("id", "outline")
        .datum({type: "Sphere"})
        .attr("d", d3.geo.path().projection(projection));

  var point = svg.selectAll("path.point").data(points);
  point.enter()
        .append("path")
          .attr("class", "point")
          .attr("d", function(d) {return pointpath(d, 0)})
            .transition()
            .delay(function(d, i){return i * 1000;})
            .duration(500)
            .attrTween("d", function(d) {
                rinterp = d3.interpolate(0, 10);
                var fn = function(t) {
                  d.r = rinterp(t);
                  return pointpath(d, d.r);
                };
                return fn;
            });
};

leeroyjenkins();