带纬度/经度输入的拖动点

时间:2019-03-08 13:01:35

标签: javascript d3.js

我一直在使用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>

1 个答案:

答案 0 :(得分:2)

在D3 v3中,您在此处使用的.origin方法...

var drag = d3.behavior.drag()
    .origin(function (d) { return d; })

...需要具有xy属性的对象。该旧版本已经过时的API说:

  

通常将原始访问者指定为身份函数:function(d) { return d; }。当绑定到被拖动元素的基准已经是具有xy属性表示其当前位置的对象时,此方法适用。

因此,最简单的解决方案是将其删除:

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>