首页 > 解决方案 > d3js:世界地图上的强制布局在缩放时重新计算

问题描述

我有一张世界地图,上面有圆圈。d3.forceSimulation重叠的圆圈不会碰撞并形成气泡。

问题发生在缩放上。如果我放大地图,圆圈会停留在原始位置,而不是形成一个新的气泡或停留在确切的位置。我怎样才能做到这一点?我读到了 force.start() 但我不能在我的缩放功能中调用它..

    var width = 1200,
        height = 500;

        var zoom = d3.zoom()
            .scaleExtent([1, 10])
            .on("zoom", zoomed);


    var projection = d3.geoMercator()
        .center([120, -20]) //long and lat starting position
        .scale(100) //starting zoom position
        .rotate([10,0]); //where world split occurs

    var worldmap = d3.select("#worldmap")
        .attr("viewBox", "0 0 " + width + " " + height )
        .attr("preserveAspectRatio", "xMinYMin meet")
        .attr("viewBox", "0 0 600 300")
        .call(zoom);

    var path = d3.geoPath()
        .projection(projection);

    var g = worldmap.append("g");

    var simulation = d3.forceSimulation()
        .force('x', d3.forceX().x(function(d) {return projection([d.LastLocation.lon, d.LastLocation.lat])[0]}))
        .force('y', d3.forceY().y(function(d) {return projection([d.LastLocation.lon, d.LastLocation.lat])[1]}))
        .force("charge", d3.forceManyBody().strength(0.5)) // Nodes are attracted one each other of value is > 0
        .force("collide", d3.forceCollide().strength(.1).radius(2).iterations(2)) // Force that avoids circle overlapping

  //Zoom functionality
    function zoomed() {
  const currentTransform = d3.event.transform;
  g.attr("transform", currentTransform);
  g.selectAll("circle")
  .attr("r", 3 - (currentTransform.k / 4))
  }

  d3.select(".zoom-in").on("click", function() {
    zoom.scaleBy(svg.transition().duration(750), 1.2);
  });
  d3.select(".zoom-out").on("click", function() {
    zoom.scaleBy(svg.transition().duration(750), 0.8);
  });

    // load and display the world and locations
    d3.json("https://gist.githubusercontent.com/d3noob/5193723/raw/world-110m2.json", function(error, topology) {

    var world = g.selectAll("path")
                    .data(topojson.object(topology, topology.objects.countries).geometries)
                    .enter()
                    .append("path")
                    .attr("d", path)
            ;


    var locations = g.selectAll("circle")
          .data(devicesAll)
          .enter()
          .append("circle")
          .attr("cx", function(d) {return projection([d.LastLocation.lon, d.LastLocation.lat])[0];})
          .attr("cy", function(d) {return projection([d.LastLocation.lon, d.LastLocation.lat])[1];})
          .attr("r", 2)
          .style("fill", "black")
          .style("opacity", 1)
          .on("mouseover", function(d) {
            var getUrl = window.location;
            $('.notebooks.map .detailview, .modules.installations .detailview').css('display', 'block');
            $('#insideCardTitle').html(d.UnitName);
            $('#insideCardLastOnline').html(d.LastOnline);
            $('#insideCardVrManV').html(d.InstalledPlatformVersion);
            $('#inside-card').attr("href", getUrl .protocol + "//" + getUrl.host + "/" + getUrl.pathname.split('/')[1] + '/notebooks/view/' + d.ID);
            d3.selectAll("g > line").remove()

          })

  // Apply these forces to the nodes and update their positions.
  // Once the force algorithm is happy with positions ('alpha' value is low enough), simulations will stop.
  simulation
      .nodes(devicesAll)
      .on("tick", function(){
        locations
            .attr("cx", function(d){ return d.x; })
            .attr("cy", function(d){ return d.y; })
      });

标签: javascriptsvgd3.jstopojson

解决方案


推荐阅读