javascript - D3.v4 投影过渡不起作用

标签 javascript d3.js

我最近才开始写代码,这是我第一次发帖,所以对任何违反协议(protocol)的行为表示歉意;-P

我正在尝试从这个 Mike Bostock bl.ock 中重现投影过渡

http://bl.ocks.org/mbostock/3711652

但在 d3.v4 中。我可以执行过渡,但中间没有动画。我认为这与我执行 ProjectionTween 函数的方式有关,或者可能与 Update 选择 svg 的方式有关,但我似乎无法做到否则工作。

如有任何帮助,我们将不胜感激。

//Options, insert projections here

var options = [
  {name: "Mercator", projection: d3.geoMercator()},
  {name: "Hammer", projection: d3.geoHammer()},
  {name: "ConicEqual", projection: d3.geoConicEqualArea()},
  {name: "ConicEqui", projection: d3.geoConicEquidistant()},
  {name: "ConicConformal", projection: d3.geoConicConformal()},
  {name: "Ginzburg8", projection: d3.geoGinzburg8()},
  {name: "Laskowski", projection: d3.geoLaskowski()},
   {name: "Times", projection: d3.geoTimes()},
  {name: "LaGrange", projection: d3.geoLagrange()}
  ];

options.forEach(function(o) {
  o.projection.rotate([0, 0]).center([0, 0]);
});

var interval = setInterval(loop, 1500),
    i = 0,
    n = options.length - 1;



var c = document.getElementById('container');

var width = c.offsetWidth;

var height = width / 2;

var div = d3.select("body").append("div") 
    .attr("class", "tooltip")       
    .style("opacity", 0);  

var graticule = d3.geoGraticule();


 
var menu = d3.select("#projection-menu")
    .on("change", change);

menu.selectAll("option")
    .data(options)
  .enter().append("option")
    .text(function(d) { return d.name; });



setup(width,height);

function setup(width,height){
    projection = options[i].projection // N.B. geoPeirceQuincuncial in 1.1+
    .translate([(width/2), (height/2)])
    .scale( width / 2 / Math.PI);

  //path = d3.geo.path().projection(projection);
  path = d3.geoPath().projection(projection);

  svg = d3.select("#container").append("svg")
      .attr("width", width)
      .attr("height", height)
      .append("g");

  g = svg.append("g");


g.append("path")
    .datum(graticule)
    .attr("class", "graticule")
    .attr("d", path); 

g.append("path")
    .datum({type: "Sphere"})
    .attr("class", "sphere")
    .attr("d", path)
    .attr("fill", "#f1f1f1")
    .attr("stroke", "black")
     .attr("opacity", 0.3);


}


d3.queue()
    .defer(d3.json, "world-50m.v1.json")
    .await(ready);

function ready(error, world) {
 
  var countries = topojson.feature(world, world.objects.countries).features;
  topo = countries;
  draw(topo);
}


function draw(topo) {


  var country = g.selectAll(".country").data(topo);

  country.enter().insert("path")
      .attr("class", "country")
      .attr("d", path)
      .style("fill", "black");
 }


//Loop / interval / option / update

function loop() {
  var j = Math.floor(Math.random() * n);
  menu.property("selectedIndex", i = j + (j >= i));
  update(options[i]);
}

function change() {
  clearInterval(interval);
  update(options[this.selectedIndex]);
}

function update(option) {
  svg.selectAll("path").transition()
      .duration(750)
      .attrTween("d", projectionTween(projection, projection = option.projection));
}

function projectionTween(projection0, projection1) {
  return function(d) {
    var t = 0;

    projection = options[i].projection // N.B. geoPeirceQuincuncial in 1.1+
    .translate([(width/2), (height/2)])
    .scale( width / 2 / Math.PI);

  //path = d3.geo.path().projection(projection);
  path = d3.geoPath().projection(projection);

    function project(λ, φ) {
      λ *= 180 / Math.PI, φ *= 180 / Math.PI;
      var p0 = projection0([λ, φ]), p1 = projection1([λ, φ]);
      return [(1 - t) * p0[0] + t * p1[0], (1 - t) * -p0[1] + t * -p1[1]];
    }

    return function(_) {
      t = _;
      return path(d);
    };


  };
}
.country {
  fill: grey;
  stroke-width: 0.1px;
}

.graticule {
  fill: none;
  stroke: grey;
  stroke-width: 0.5px;
  stroke-opacity: 0.3;
}

#container {
  margin:10px 10%;
  border:2px solid #000;
  border-radius: 5px;
  height:100%;
  overflow:hidden;
  background: none;
}
<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <select id="projection-menu"></select>
</head>
<body>
    <div id="container"></div>
    <script src="//d3js.org/d3.v4.min.js"></script>
    <script src="//d3js.org/d3-geo-projection.v1.min.js"></script>
    <script src="//d3js.org/topojson.v2.min.js"></script>
    <script src="https://d3js.org/d3-scale-chromatic.v1.min.js"></script>
</body>
</html>

Playground

最佳答案

我想通了!我误解了 projectionTween 函数的工作原理。我基本上忘了将它从 v3 过渡到 v4。所以代码:

var projection = d3.geo.projection(项目) .scale(1) .translate([宽度/2, 高度/2]);

变成:

var projection = d3.geoProjection(项目) .scale(1) .translate([宽度/2, 高度/2]);

希望这对某人有帮助!

关于javascript - D3.v4 投影过渡不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40841884/

相关文章:

javascript - 在 JavaScript 或 jQuery 中动态设置 div id

javascript - 如何使用 d3.js 在圆内创建 voronoi 图

Angular - 缩放在代码中创建的内联 d3 SVG

javascript - 检测复选框是否被选中,然后获取 div id

javascript - 在javascript中将回调函数设置为新窗口

javascript - Chrome Profiler Javascript 内存泄漏

javascript - 椭圆弧箭头边d3力布局

javascript - D3 树形图更新 - 并非所有元素都被删除

javascript - 链接到从 SVG 生成的下载文件

javascript - Express 项目中的嵌套路由