【问题标题】:Initiate d3 map over certain area given latitude and longitude在给定纬度和经度的特定区域上启动 d3 地图
【发布时间】:2023-03-05 15:56:02
【问题描述】:

我正在 d3 中构建地图,并以 Andy Barefoot 的这个 codepen 为基础:https://codepen.io/nb123456/pen/zLdqvM?editors=0010。我想修改initiateZoom() 函数,以便如果我为俄亥俄州周围的框设置纬度/经度坐标,地图将初始化其平移到俄亥俄州。

function initiateZoom() {
  minZoom = Math.max($("#map-holder").width() / w, $("#map-holder").height() / h);
  maxZoom = 20 * minZoom;

  zoom
    .scaleExtent([minZoom, maxZoom])
    .translateExtent([[0, 0], [w, h]])
  ;

  midX = ($("#map-holder").width() - minZoom * w) / 2;
  midY = ($("#map-holder").height() - minZoom * h) / 2;//These are the original values
  var swlat = 32;
  var swlon = -82;
  var nelat = 42;
  var nelon = -72;
  var projectCoordinates = projection([(swlat+nelat)/2, (swlon+nelon)/2]);

  /*This did not work
  var midX =  minZoom*(w-(swlat+nelat)/2) - ($("#map-holder").width()-(swlat+nelat)/2);
  var midY = minZoom*(h-(swlon+nelon)/2) - ($("#map-holder").height()-(swlon+nelon)/2);*/
  /*Neither did this
  var midX = minZoom*(w-projectCoordinates[0])-($("#map-holder").width()-projectCoordinates[0]);
  var midY = minZoom*(h-projectCoordinates[1])-($("#map-holder").height()-projectCoordinates[1]);*/

  svg.call(zoom.transform, d3.zoomIdentity.translate(midX, midY).scale(minZoom));
}  

原始方法背后的想法是:

1: Get the current pixel display of the map
2: Get the new pixel distance from the map corner to the map point after zoom has been applied 
3: The pixel distance of the center of the container to the top of the container
4: subtract the values from 2 and 3

原始帖子试图翻译地图,以便初始化缩放并在地图中心平移。我首先尝试通过将纬度/经度值直接代入上述方程来修改这种方法。我还尝试首先使用投影转换纬度/经度值,然后将这些值代入,但收效甚微。我需要做什么才能获得我想要的结果?

【问题讨论】:

  • 我现在不能看太多,但是将它们传递给投影时,您的纬度/经度值会反转:您使用的是projection([lat,lon]),但它的projection([lon,lat]) - 这可能没有解决任何问题,但如果没有,这肯定会使您注释掉的代码的问题更加复杂。

标签: javascript d3.js


【解决方案1】:

设置translateExtent 可能不是一个好主意,因为它取决于缩放比例。

以下替换有效。

function initiateZoom() {
  // Define a "minzoom" whereby the "Countries" is as small possible without leaving white space at top/bottom or sides
  minZoom = Math.max($("#map-holder").width() / w, $("#map-holder").height() / h);
  // set max zoom to a suitable factor of this value
  maxZoom = 20 * minZoom;
  // set extent of zoom to chosen values
  // set translate extent so that panning can't cause map to move out of viewport
  zoom
    .scaleExtent([minZoom, maxZoom])
    .translateExtent([[0, 0], [w, h]])
  ;

  var swlat = 32;
  var swlon = -82;
  var nelat = 42;
  var nelon = -72;
  var nwXY = projection([swlon, nelat]);
  var seXY = projection([nelon, swlat]);
  var zoomScale = Math.min($("#map-holder").width()/(seXY[0]-nwXY[0]), $("#map-holder").height()/(seXY[1]-nwXY[1]))
  var projectCoordinates = projection([(swlon+nelon)/2, (swlat+nelat)/2]);

  svg.call(zoom.transform, d3.zoomIdentity.translate($("#map-holder").width()*0.5-zoomScale*projectCoordinates[0], $("#map-holder").height()*0.5-zoomScale*projectCoordinates[1]).scale(zoomScale));
}

【讨论】:

  • 不错的答案,但你的推理有点不对劲,西经 小于东经:西经 -82,东经 -72。在答案中,您实际上将西经度置于最东端,反之亦然(-80 位于 -84 以东)。这仍然可以工作,因为具有这四个坐标的任何 2 个不同的纬度/经度对将形成对角,并且您在比例函数中使用西减东(因为西经的 x 值应小于东 x 值,您应该有一个负值,除非你交换了东和西的值)。
  • @AndrewReid:正确。我交换了角落,但计算就像它在左上角和右下角一样。我会修改代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-21
  • 2012-09-23
  • 1970-01-01
  • 1970-01-01
  • 2016-11-11
相关资源
最近更新 更多