D3.v4投影转换不起作用

时间:2016-11-28 10:21:10

标签: javascript d3.js

我最近才开始编码,这是我第一次发帖,所以对任何违反协议的行为表示道歉;-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

1 个答案:

答案 0 :(得分:2)

我明白了!我误解了projectionTween函数是如何工作的。我基本上忘了把它从v3转换到v4。所以代码:

var projection = d3.geo.projection(project)     .scale(1)     .translate([width / 2,height / 2]);

变为:

var projection = d3.geoProjection(project)     .scale(1)     .translate([width / 2,height / 2]);

希望这有助于某人!