如何在 D3v6 中使地图可拖动
How to make map draggable in D3v6
我有一个 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. This is the code from 一个问题。当地图放大时,它变得可拖动。我没有看到代码中任何地方定义了拖动行为。我假设它是通过使用 d3.zoom()
实现的。但是,由于我的地图在默认情况下(加载时)是放大的,并且我有一个单独的鼠标单击事件,所以我认为我不能使用类似的方法。
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,现在地图工作正常。
我有一个 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. This is the code from d3.zoom()
实现的。但是,由于我的地图在默认情况下(加载时)是放大的,并且我有一个单独的鼠标单击事件,所以我认为我不能使用类似的方法。
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,现在地图工作正常。