【问题标题】:Add Static Lines on D3 Map Between Latitude and Longitude Points在纬度和经度点之间的 D3 地图上添加静态线
【发布时间】:2015-07-17 10:39:12
【问题描述】:

我有一张 D3 世界地图,上面标有我感兴趣的经纬度点。

现在我想绘制连接这些点的简单静态线。我该怎么做?

这是我的带有标记的地图代码:

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>

    var width = 900,
            height = 500;

    // Create Projection
    var projection = d3.geo.mercator()

    // Generate paths based on projection
    var path = d3.geo.path()
            .projection(projection);

    // Create SVG
    var svg = d3.select("body").append("svg")
            .attr("width", width)
            .attr("height", height);

    // Group for the map features
    var features = svg.append("g")
            .attr("class","features");

    // Build map with markers
    d3.json("countries.topojson",function(error,geodata) {
        if (error) return console.log(error);

        //Create a path for each map feature in the data
        features.selectAll("path")
                .data(topojson.feature(geodata, geodata.objects.subunits).features)
                .enter()
                .append("path")
                .attr("d", path)
        // Add markers for cities by their latitude and longitude.
        d3.csv("cities.csv", function (error, data) {
            features.selectAll("circle")
                    .data(data)
                    .enter()
                    .append("circle")
                    .attr("cx", function (d) {
                        return projection([d.lon, d.lat])[0];
                    })
                    .attr("cy", function (d) {
                        return projection([d.lon, d.lat])[1];
                    })
                    .attr("r", 5)
                    .style("fill", "red");

        });
    });
</script>

cities.csv:

name,lat,lon
LA,34.05,-118.25
NY,40.7127,-74.006

这段代码产生如下内容:

现在我想用线条连接标记。只是一条静态线,不需要动画或任何东西。结果应如下所示:

我为d3.json() 调用上方的行添加了一个新组:

var lines = features.append("g");

然后在 d3.json() 调用中,我添加类似这样的内容来创建线坐标数组:

   var theLines = [
                {
                    type: "LineString",
                    coordinates: [
                        [ data[0].lon, data[0].lat ],
                        [ data[1].lon, data[1].lat ]
                    ]
                }
            ];

但我不确定下一步该做什么(或者我的方法是否正确)以实际添加连接标记的行。

我想使用 CSS 来设置标记和线条的颜色和大小。

更新:

我尝试更改圆圈的代码以画一条线,但它不起作用:

根据srbdev's 的回答,我将lineString 更改为line

d3.csv("cities.csv", function (error, data) {
    features.selectAll("line")
            .data(data)
            .enter()
            .append("line")
            .attr("x1", function (d) {
                return projection([d.lon])[0];
            })
            .attr("y1", function (d) {
                return projection([d.lat])[0];
            })
            .attr("x2", function (d) {
                return projection([d.lon])[1];
            })
            .attr("y2", function (d) {
                return projection([d.lat])[1];
            })
            .style("stroke", "red");
});

但我得到以下结果:x2y2 在控制台中有 "NaN" 值。

【问题讨论】:

  • D3 方法是从您的 cities 数据中为链接构建数据(例如,简单的带有开始和结束城市的 2 元素数组)并使用它来添加行。最简单的方法可能是使用 line 元素和直接从数据中获取的坐标,其方式与您目前为城市添加圆圈的方式类似。
  • 谢谢拉斯。你能给我一个例子吗?我更新了我的问题,我尝试修改我的代码以绘制一条线而不是点。
  • 那么您如何确定应该在哪些城市之间划线?

标签: javascript d3.js


【解决方案1】:

在您的编辑中,您应该将代码更改为:

d3.csv("cities.csv", function (error, data) {
features.selectAll("line")
        .data(data)
        .enter()
        .append("line")
        .attr("x1", function (d) {
            return projection([d.lon])[0];
        })
        .attr("y1", function (d) {
            return projection([d.lat])[0];
        })
        .attr("x2", function (d) {
            return projection([d.lon])[1];
        })
        .attr("y2", function (d) {
            return projection([d.lat])[1];
        })
        .style("stroke", "yellow"); 
});   

我将“lineString”更改为“line”。有关可用 SVG 元素的列表,请参阅link

另一种解决方案,虽然不是 Lars 提到的真正的 D3 方式,是为每个圆圈分配一个 ID,并按如下方式创建您的线:

svg.append("line")
    .attr("x1", d3.select("#circle1").attr("cx"))
    .attr("y1", d3.select("#circle1").attr("cy"))
    .attr("x2", d3.select("#circle2").attr("cx"))
    .attr("y2", d3.select("#circle2").attr("cy"))
    .style("stroke", "yellow");

希望这会有所帮助!

【讨论】:

  • 谢谢。我尝试了您的第一个解决方案。它有点工作,但我得到了一些奇怪的结果。请使用新的屏幕截图查看我更新的问题。 x2 和 y2 返回“NaN,因此这些行都在原点结束。由于某种原因,它还添加了 2 行。
  • 我明白了……它之所以如此,是因为您使用 d3.data 和 d3.enter 函数,它们将为每个数据点绘制两次线。您需要提取这些数据点并直接绘制线条,而无需使用 d3.selectAll、d3.data 和 d3.enter。对于行的属性,例如使用 .attr("x1", data[0].lon) 等...如果您可以将代码放在 jsfiddle 或类似的东西中,我可以为您编辑它。
  • 抱歉,请使用 .attr("x1", function() { return projection(data[0].lon); }) 之类的内容作为行的属性。
  • 所以我在我用来表达观点的 d3.csv("cities.csv", function(){...}) 中执行此操作?还是我需要第二个 d3.csv()?我已经尝试了两种方法,但我仍然得到一些“NaN”值。在元素检查器中,我看到 x1="NaN,247.38187319746223"。不知道为什么它为 x1 设置 2 个值。它为每个 x 和 y 设置 2 个值。我无法获得小提琴,我无法上传 country.topojson 文件
  • 是的,它仍然会在 d3.csv("cities.csv", function() { ... }) 中。听起来您快到了,但没有从回调中看到您的数据格式,我无法确定如何返回您的线路属性。
猜你喜欢
  • 2016-11-11
  • 2013-08-12
  • 1970-01-01
  • 2017-08-19
  • 2017-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多