【问题标题】:How can I move a d3 map using zoom behavior and transforms?如何使用缩放行为和变换移动 d3 地图?
【发布时间】:2019-12-01 20:34:34
【问题描述】:

我正在使用 d3v4 构建地图。我正在使用 Robinson 投影、d3 的缩放行为进行平移和缩放,以及 css 转换来实际定位 svg 元素本身。给定一个经纬度对,我想使用当前缩放使地图居中。

我已经看到了很多关于如何在 d3 中居中地图以及如何附加缩放行为的示例,但到目前为止,每个示例都是

给定一个纬度/经度对,我可以使用我的投影来获得非翻译、非缩放 svg 上的 X/Y。如何从该点创建转换以使其在视图中居中?

我的地图设置:

const {clientHeight: height, clientWidth: width} = div;
svg.setAttribute("width", `${width}`);
svg.setAttribute("height", `${height}`);

// projection
this.projection = geoRobinson()
    // center and scale to container properly
    .translate([width / 2, height / 2])
    .scale((width - 1) / 2 / Math.PI);

// calculate zoom limits
const actualHeight = width / ratio;
const verticalExtent = (actualHeight - height) / 2;

// setup mouse listeners for panning and zooming on svg.
this.zoomBehavior = zoom<SVGSVGElement, any>()
    // set min and max zoom factor
    .scaleExtent([0.75, 8]) // based on playing around with numbers until it looked pleasing

    // transform map on zoom and pan
    .on("zoom", () => {
        const currentTransform = this.state.transform;
        const newTransform: ZoomTransform = d3event.transform;

        if (
            !currentTransform ||
            hasChanged(currentTransform.x, newTransform.x) ||
            hasChanged(currentTransform.y, newTransform.y) ||
            hasChanged(currentTransform.k, newTransform.k)
        ) {
            this.setState({ // updates the css transform of the SVG map
                transform: newTransform,
            });
        }
    });

// apply zoom behavior to whole svg
const svgSelection = select(svg);

svgSelection.call(this.zoomBehavior)

我查看了zoomBehavior.translateTo() 和其他函数,但我不知道如何转换为它们使用的任何单位。

【问题讨论】:

    标签: d3.js svg


    【解决方案1】:

    经过大量修补和谷歌搜索,我找到了这个例子:https://bl.ocks.org/andybarefoot/765c937c8599ef540e1e0b394ca89dc5

    它具有 d3v4、缩放行为以及根据命令重新定位地图的能力。


    我要做的是:

    1. 获取原点的像素位置,如同地图未缩放(或缩放 = 1)
    2. 如果原点移动到视图中心并缩放,则使用公式获取 css 变换。对于 x:(width / 2) - (longitude * zoom)
    3. 使用svg.call(behavior, newTransform) 应用转换(显然也更新了行为。或者它不需要更新。)

    我的代码:

    const coords = this.projection([longitude, latitude]);
    if (!coords) {
        return;
    }
    
    let actualScale: number = 1;
    if (scale !== undefined) {
        actualScale = Math.min(MAX_ZOOM, Math.max(MIN_ZOOM, 1, scale));
    }
    
     // get pixel size of svg
    const {clientHeight: height, clientWidth: width} = svg;
    
    // build new transform
    const transform = zoomIdentity
        .translate(width / 2 - coords[0] * actualScale, height / 2 - coords[1] * actualScale)
        .scale(actualScale);
    
    // apply and save transform
    select(svg)
        .transition() // omit this and the next line if you don't want transitions
        .duration(200)
        .call(this.zoomBehavior.transform, transform);
    

    【讨论】:

      猜你喜欢
      • 2013-12-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-29
      • 1970-01-01
      • 2017-08-22
      • 1970-01-01
      相关资源
      最近更新 更多