匹配的传单缩放级别与d3地理比例

时间:2014-02-18 16:38:52

标签: javascript svg d3.js gis leaflet

我想做什么?

  • 在传单(或任何地图框架)上叠加SVG图层。
  • 在我的SVG图层中使用d3js和d3.geo.mercator位置元素,使它们正确放置在传单上。
  • 我只能访问缩放级别,地图中心(纬度/经度),地图SVG元素的宽度和高度。
  • 我只需要听一下缩放级别和地图中心的更改,以便知道何时重新定位我的SVG元素。

我已经使SVG元素的尺寸与传单层相同;并将其作为叠加层。

我现在怎么做?

我有一些与传单值相符的全局变量(Map.zoom,Map.width,Map.height,Map.center)。

Map.center = [43, -72];
Map.zoom = 3;

Map.projection = d3.geo.mercator()
            .center([Map.center[1], Map.center[0]])
             // I think this is the problem. I don't really understand this.
            .scale(256 * Math.pow(2, Map.zoom))
            .translate([Map.width / 2, Map.height / 2])

Map.lt = new L.Map...(center is Map.center, zoom is Map.zoom)

任何时候传单更改我都会更新全局值并重新计算Map.projection。

我有一个功能:

function transform(d) {
    d = Map.projection(d.value.geometry.coordinates[0], d.value.geometry.coordinates[1]);

    return "translate(" + d[0] + "," + d[1] + ")";
}

然后在我需要定位的对象和元素上调用:

object.attr("transform", transform);

我的问题是图层不同步。

当我将地图放在[43,-72]中心时,我看到返回的x,y值(来自Map.projection)它正好在我的SVG图层中间,所以我猜错了我的规模。我不确定如何正确排列这些值。

我不想使用d3.geo.tile或d3.geo.path(),因为我需要更灵活地控制元素的定位和动画。

我只想知道如何利用d3功能排列传单与SVG图层的位置。我不希望依靠传单来定位我的物品,因为我将来可能不会使用传单;我只需要能够缩放/翻译我的d3.geo.mercator投影,使其与传单对齐。我怎么能这样做?

谢谢!

Example

2 个答案:

答案 0 :(得分:3)

Map.projection = d3.geo.mercator()
            .center([Map.center[1], Map.center[0]])
            .scale((1 << 8 + Map.zoom) / 2 / Math.PI)
            .translate([Map.width / 2, Map.height / 2])

不确定它是如何工作的,但看了一些其他的例子并弄明白了。

答案 1 :(得分:0)

这就是我最终得到的结果(不要对JS的陌生感到惊讶 - 它是ES6):

        UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
        [button addTarget:self action:@selector(method) forControlEvents:UIControlEventTouchUpInside];
        [button setTitle:@"< Back" forState:UIControlStateNormal];
        button.frame = CGRectMake(0, 15, 60, 10);
        button.titleLabel.font = [UIFont systemFontOfSize:12];
       [ button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [self.authorizationWebView addSubview:button];

测试:

const convertZoomLevelToMercator = (zoomLevel) =>
  Math.pow(2, 8 + zoomLevel) / 2 / Math.PI;
const convertZoomLevelFromMercator = (zoomLevelInMercator) =>
  Math.log(zoomLevelInMercator * 2 * Math.PI) / Math.LN2 - 8;

输出:

console.log(convertZoomLevelToMercator(1));
console.log(convertZoomLevelToMercator(5));
console.log(convertZoomLevelToMercator(10));
console.log(convertZoomLevelToMercator(15));
console.log(convertZoomLevelToMercator(20));
console.log('----');
console.log(convertZoomLevelFromMercator(convertZoomLevelToMercator(1)));
console.log(convertZoomLevelFromMercator(convertZoomLevelToMercator(5)));
console.log(convertZoomLevelFromMercator(convertZoomLevelToMercator(10)));
console.log(convertZoomLevelFromMercator(convertZoomLevelToMercator(15)));
console.log(convertZoomLevelFromMercator(convertZoomLevelToMercator(20)));