【问题标题】:How to make map draggable in D3v6如何在 D3v6 中使地图可拖动
【发布时间】:2021-08-28 11:14:54
【问题描述】:

我有一个 Drilldown 世界地图(大陆地图 + 国家地图),其中第二张地图(国家地图)使用 fitExtent 函数在加载时放大。由于它是放大的,我想实现一个可拖动的功能,我可以拖动地图并查看地图的其他部分。

//My svg tag
<svg id="mapSVG" width="560"; height="350"></svg>

let zoomControl = function (event) {
    svg.selectAll("path")
        .attr("transform", event.transform);
}

function loadCountryMap(path, mapData) {
    d3.json(path).then(function (json) {
        var projection = d3.geoMercator();
        var features = json.features;

        //The reason why we have to do this is because d3.js has winding problem
        //We need to rewind for the map to display correctly
        var fixed = features.map(function (feature) {
            return turf.rewind(feature, { reverse: true });
        })
        //Projections
        var geoPath = d3.geoPath().projection(projection);

        //Zoom in
        projection.fitExtent([[mapData.XOffSet, mapData.YOffSet], [width*2, height*2]], { "type": "FeatureCollection", "features": fixed })

        //Draggable
        svg.selectAll("path")
            .data(fixed)
            .enter()
            .append("path")
            .attr("d", geoPath)
            .attr("id", function (d) { return d.properties.FIPS_10_; })
            .style("fill", "steelblue")
            .style("stroke", "transparent")
            .on("mouseover", mouseOver)
            .on("mouseleave", mouseLeave)
            .on("click", mouthClick)
            .call(d3.zoom()
                .on("zoom", zoomControl)
                .scaleExtent([1, 1])
            )
    })
}

//How I select the svg
var svg = d3.select("svg")
    .style("background-color", "white")
    .style("border", "solid 1px black");
var width = +svg.attr("width");
var height = +svg.attr("height");

这样做有两个问题:

1:通过选择“svg”标签,这将拖动整个 SVG HTML 元素,而不是 SVG 的地图内容。我也改成了“path”和“d”,也没用。

2:第一次发生拖动事件时,被拖动的元素被放置在鼠标光标的右下角,然后跟随鼠标光标移动。

我希望放大的地图可以拖动到地图的其他部分。

示例所需的行为bin。这是从Andrew Reid's answer 到问题的代码。放大地图后,它变成了可拖动的。我没有看到代码中任何地方都定义了拖动行为。我假设它是通过使用d3.zoom() 来实现的。但是,由于我的地图默认是放大的(onload),并且我有一个单独的鼠标点击事件,我认为我不能使用类似的方法。

【问题讨论】:

  • 要使地图在初始加载时可拖动,您可以在 zoom 处理程序中注释掉 .translateExtent([[0,0],[width,height]])。这就是你想要达到的目标吗?
  • @RobinMackenzie 是的,这正是我想要的,但在我的方法中,我没有缩放处理程序。我使用fitExtent 来实现缩放功能。我的钻取地图的工作方式是,例如,当用户单击北美大陆时,第二张地图将使用 fitExtent 以已经放大的方式呈现,所以我没有缩放处理程序
  • Drag 带有缩放功能,所以您可能需要在第二张地图上进行缩放,这样它也可以左右拖动?
  • @RobinMackenzie 哦,我不知道拖动带有缩放。让我快速看看
  • @RobinMackenzie 我已经实现了该功能,但它确实有问题。例如,当我拖动时,地图会前后振动/跳跃。当我从 bin 中删除 '.append("g")' 行时,它会遇到同样的问题。我已经更新了我的回答,以反映我现在的情况,你能看一下吗?

标签: javascript d3.js zooming draggable


【解决方案1】:
var svg = d3.select("#mapDiv")
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .style("background-color", "white")
    .style("border", "solid 1px black")
    .call(d3.zoom()
        .on("zoom", function (event) {
            svg.attr("transform", event.transform)
        })
        .scaleExtent([1, 1])
    )
    .append("g");

我通过将路径与.append("g") 分组来实现该功能。我没有按路径分配缩放功能路径,而是将其分配给整个 SVG,现在地图工作正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-06-22
    • 1970-01-01
    • 1970-01-01
    • 2014-01-17
    • 2015-06-29
    • 2016-08-11
    • 2016-09-15
    • 1970-01-01
    相关资源
    最近更新 更多