我一直在使用this example来启用点的拖动。成功的JS提琴here。
我的问题是,如何将其转换为使用基于纬度/经度的坐标系的输入数据?
我可以很好地显示/投影点,但是当我拖动它时,它固定在左上角。 DevTools控制台返回错误“错误:属性cx:预期长度“ NaN”。属性cy返回相同。
我认为这与拖动功能有关,但是我尝试过的所有排列都失败了。
var width = Math.max(960, window.innerWidth),
height = Math.max(500, window.innerHeight) - 90;
var tile = d3.geo.tile()
.size([width, height]);
var projection = d3.geo.mercator()
.scale((1 << 23) / 2 / Math.PI)
.translate([-width / 2, -height / 2]);
var drag = d3.behavior.drag()
.origin(function (d) { return d; })
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended);
var container = d3.select("body").append("div")
.attr("id", "container")
.style("width", width + "px")
.style("height", height + "px");
var points = container.append("svg")
.attr("id", "points");
var nodes_data_latlng = [{ "lat1": -0.01, "lng1": 0.025 }];
drawnodeslatlng();
function drawnodeslatlng() {
d3.select("#points").selectAll("circle")
.data(nodes_data_latlng)
.enter()
.append("circle")
.attr("cx", function (d) { return projection([d.lng1, d.lat1])[0] })
.attr("cy", function (d) { return projection([d.lng1, d.lat1])[1] })
.attr("r", "10")
.call(drag)
}
function dragstarted(d) {
d3.event.sourceEvent.stopPropagation();
d3.select(this).classed("dragging", true);
}
function dragged(d) {
d3.select(this)
.attr("cx", d.lng1 = d3.event.x)
.attr("cy", d.lat1 = d3.event.y);
}
function dragended(d) {
d3.select(this).classed("dragging", false);
}
<html>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://d3js.org/d3.geo.tile.v0.min.js"></script>
</body>
</html>
答案 0 :(得分:2)
在D3 v3中,您在此处使用的.origin
方法...
var drag = d3.behavior.drag()
.origin(function (d) { return d; })
...需要具有x
和y
属性的对象。该旧版本已经过时的API说:
通常将原始访问者指定为身份函数:
function(d) { return d; }
。当绑定到被拖动元素的基准已经是具有x
和y
属性表示其当前位置的对象时,此方法适用。
因此,最简单的解决方案是将其删除:
var width = Math.max(960, window.innerWidth),
height = Math.max(500, window.innerHeight) - 90;
var tile = d3.geo.tile()
.size([width, height]);
var projection = d3.geo.mercator()
.scale((1 << 23) / 2 / Math.PI)
.translate([-width / 2, -height / 2]);
var drag = d3.behavior.drag()
.on("dragstart", dragstarted)
.on("drag", dragged)
.on("dragend", dragended);
var container = d3.select("body").append("div")
.attr("id", "container")
.style("width", width + "px")
.style("height", height + "px");
var points = container.append("svg")
.attr("id", "points");
var nodes_data_latlng = [{ "lat1": -0.01, "lng1": 0.025 }];
drawnodeslatlng();
function drawnodeslatlng() {
d3.select("#points").selectAll("circle")
.data(nodes_data_latlng)
.enter()
.append("circle")
.attr("cx", function (d) { return projection([d.lng1, d.lat1])[0] })
.attr("cy", function (d) { return projection([d.lng1, d.lat1])[1] })
.attr("r", "10")
.call(drag)
}
function dragstarted(d) {
d3.event.sourceEvent.stopPropagation();
d3.select(this).classed("dragging", true);
}
function dragged(d) {
d3.select(this)
.attr("cx", d.lng1 = d3.event.x)
.attr("cy", d.lat1 = d3.event.y);
}
function dragended(d) {
d3.select(this).classed("dragging", false);
}
<html>
<body>
<script src="https://d3js.org/d3.v3.min.js"></script>
<script src="https://d3js.org/d3.geo.tile.v0.min.js"></script>
</body>
</html>