有没有办法限制可以在D3.js地图上拖动对象的区域?在this example中,用户可以将对象拖动到投影边界之外,这是我想要避免的。
有什么想法吗?谢谢!
var drag = d3.behavior.drag()
.on("drag", function(d) {
var x = d3.select(this).attr("x");
var y = d3.select(this).attr("y");
var dx = d3.event.x - x;
var dy = d3.event.y - y;
d3.select(this).attr("transform", "translate(" + dx + "," + dy + ")");
});
function putCircle(x, y) {
d3.select('svg')
.append('path')
.attr("class", "projected")
.attr("x", x).attr("y", y)
.datum(d3.geo.circle().origin(projection.invert([x, y])).angle(5))
.attr('d', d3.geo.path().projection(projection))
.call(drag);
}
答案 0 :(得分:0)
可能有更简单的方法,但我已经使用此方法根据投影重新调整栅格。
首先,对于诸如正交投影之类的投影,projection.invert
将返回任何svg点的有效地理点,无论它是否在明显的投影区域内。
其次,对于像Aitoff这样的投影,projection.invert
将返回未定义的svg点,这些点位于投影区域之外。
这些类别中有许多预测。
因此,您需要进行两次检查以确定点是在投影区域内部还是外部。这两项检查都依赖于projection.invert
。
第一个很简单,除非定义projection.invert([d3.event.x,d3.event.y])
,否则不要拖动点。
第二个涉及正投影等预测。由于projection.invert
总是为这些投影返回有效的地理点,我们可以应用前向投影来查看返回的svg点是否等于我们开始的svg点。基本上我们想在以下时间拖动点:projection(projection.invert([x,y]) == [x,y]
。由于projection.invert
对于这些预测并非一对一,因此并非总是如此。
为了避免潜在的舍入误差,我扩展了上面的比较(不幸的是,需要打破坐标的x和y分量):
if (
Math.abs(projection(projection.invert([d3.event.x,d3.event.y]))[0] - d3.event.x) < 0.5
&&
Math.abs(projection(projection.invert([d3.event.x,d3.event.y]))[1] - d3.event.y) < 0.5) {
d3.select(this).attr("transform", "translate(" + dx + "," + dy + ")");
}
然后我们一起进行两项检查,从要求不高的第一次检查开始,然后仅在第一次检查时进行第二次检查。
更新后的fiddle is here。