d3 美国带标记的州地图,缩放变换问题
Posted
技术标签:
【中文标题】d3 美国带标记的州地图,缩放变换问题【英文标题】:d3 US state map with markers, zooming transform issues 【发布时间】:2016-03-23 06:08:50 【问题描述】:按照这个例子,我创建了一个包含美国各州的 d3 地图:
http://bl.ocks.org/mbostock/4699541
并在这个 SO 问题之后添加了标记:
Put markers to a map generated with topoJSON and d3.js
问题是在缩放时,地图标记保持在原位。我认为我需要将它们转化为新的职位,但不知道如何实现。
var width = 900,
height = 500,
active = d3.select(null);
var projection = d3.geo.albersUsa()
.scale(1000)
.translate([width / 2, height / 2]);
var path = d3.geo.path()
.projection(projection);
var svg = d3.select(".rebates").append("svg")
.attr("width", width)
.attr("height", height);
svg.append("rect")
.attr("class", "background")
.attr("width", width)
.attr("height", height)
.on("click", reset);
var g = svg.append("g")
.style("stroke-width", "1.5px");
d3.json("/files/d3-geo/us.json", function(error, us)
if (error) throw error;
g.selectAll("path")
.data(topojson.feature(us, us.objects.states).features)
.enter().append("path")
.attr("d", path)
.attr("class", function(item)
return window.US_STATES[item.id].water_authorities > 0 ? 'avail' : 'unavail';
)
.on("click", clicked);
g.append("path")
.datum(topojson.mesh(us, us.objects.states, function(a, b) return a !== b; ))
.attr("class", "mesh")
.attr("d", path);
);
d3.json('/files/coordinates.json', function(error, coords)
if (error) throw error;
svg.selectAll(".mark")
.data(coords)
.enter()
.append("image")
.attr('class','mark')
.attr('width', 20)
.attr('height', 20)
.attr("xlink:href",'assets/gmap_red.png')
.attr("transform", function(d)
return "translate(" + projection([d[1],d[0]]) + ")";
);
);
function clicked(d)
if (active.node() === this) return reset();
if (window.US_STATES[d.id].water_authorities === 0) return;
active.classed("active", false);
active = d3.select(this).classed("active", true);
var bounds = path.bounds(d),
dx = bounds[1][0] - bounds[0][0],
dy = bounds[1][1] - bounds[0][1],
x = (bounds[0][0] + bounds[1][0]) / 2,
y = (bounds[0][1] + bounds[1][1]) / 2,
scale = .9 / Math.max(dx / width, dy / height),
translate = [width / 2 - scale * x, height / 2 - scale * y];
g.transition()
.duration(750)
.style("stroke-width", 1.5 / scale + "px")
.attr("transform", "translate(" + translate + ")scale(" + scale + ")");
function reset()
active.classed("active", false);
active = d3.select(null);
rebatesTable.clear().draw();
g.transition()
.duration(750)
.style("stroke-width", "1.5px")
.attr("transform", "");
【问题讨论】:
我会将投影更改为缩放,然后使用更改后的投影重新计算标记的位置。 【参考方案1】:第 1 步
在组中添加所有点,而不是在 svg 中。 这将确保标记点与主组一起平移。
g.selectAll(".mark")//adding mark in the group
.data(marks)
.enter()
.append("image")
.attr('class', 'mark')
.attr('width', 20)
.attr('height', 20)
.attr("xlink:href", 'https://cdn3.iconfinder.com/data/icons/softwaredemo/PNG/24x24/DrawingPin1_Blue.png')
.attr("transform", function(d)
return "translate(" + projection([d.long, d.lat]) + ")";
);
第二步
否定主组的缩放效果。否则标记会放大。
g.selectAll(".mark")
.transition()
.duration(750)
.attr("transform", function(d)
var t = d3.transform(d3.select(this).attr("transform")).translate;//maintain aold marker translate
return "translate(" + t[0] +","+ t[1] + ")scale("+1/scale+")";//inverse the scale of parent
);
第三步
在缩小时使标记缩放回 1。
g.selectAll(".mark")
.attr("transform", function(d)
var t = d3.transform(d3.select(this).attr("transform")).translate;
console.log(t)
return "translate(" + t[0] +","+ t[1] + ")scale("+1+")";
);
工作代码here
希望这会有所帮助!
【讨论】:
非常好的答案,谢谢!我通过添加 .transform().duration(750)(在 .attr(...) 之前)对第 3 步做了一个小改进,它在缩小时添加了与放大时相同的缓动。 如何在缩放时保持标记的相对位置,而不是将其移动到所选状态路径的中心? 在clicked
函数中计算翻译,您必须相应地更新它..使标记位于中心
您能否更具体地说明示例代码中对第 110-116 行的更改,这将允许引脚在放大时保持在状态形状中的相同位置?谢谢
问题发布:***.com/questions/39796327/… 以及答案:jsbin.com/barekeyaca/edit?html,output以上是关于d3 美国带标记的州地图,缩放变换问题的主要内容,如果未能解决你的问题,请参考以下文章
使用 GADM shapefile 为美国地图绘制较粗的州边界和较细的县边界