d3线和csv数据在地图上的点 [英] d3 line and points on map from csv data

查看:94
本文介绍了d3线和csv数据在地图上的点的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图绘制单个数据点以及在这些点之间运行的直线路径,例如本示例

I am trying to plot individual data points and also a line path that runs between these points like this example D3 stop and restart transition along path to allow click through to geo data coordinates that I have been helped with before.

现在,我想使用我的实际数据,而不是一组测试坐标,但是遇到了麻烦.我已经尝试了geoJson文件和csv作为我的数据.我正在使用带有lon和lat的csv文件来表示点,并希望从同一组数据中制作直线,即使用一组数据来表示点和线.

Now I want to use my actual data rather than a test set of coordinates but am running into trouble. I have tried both a geoJson file and also csv for my data. I am using a csv file with lon and lat for the points and was hoping to make the line from that same set of data, ie use one set of data for the points and line.

我的线无法显示在正确的位置-它位于右上角,但应位于/通过点.我认为这与投影有关,但是我在正确解析数据以获取所需的行字符串时遇到了麻烦.我尝试在此处使用示例

I can’t get my line to show up in the correct place - it is in top right corner but should be on / through points. I think this is something to do with projection but I am having trouble parsing the data correctly to get a line string as required. I have tried to use the sample here

我的问题是如何在d3 svg线生成器中使用csv lon lat. 这是我的代码:

My question is how to use the csv lon lat with a d3 svg line generator. This is my code:

<!DOCTYPE html>
<html lang="en">
    <head>
<meta charset="utf-8">
<title>Working version 3</title>

<script src="https://d3js.org/d3.v4.min.js"></script>
<script src="https://d3js.org/d3-array.v1.min.js"></script>
<script src="https://d3js.org/d3-geo.v1.min.js"></script>
<script src="https://d3js.org/d3-queue.v3.min.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<style type="text/css">

circle {
  fill: steelblue;
  stroke: pink;
  stroke-width: 3px;
}


.line{
  fill: none;
  stroke: red;
  stroke-width: 6;

}

</style>
</head>
<body>

<script>

    var w = 960,
        h = 500;

    var projection = d3.geoMercator()
                         .translate([w/2, h/2])
                         .scale([w * 0.16]);

    var path = d3.geoPath()
                 .projection(projection);

    var duration = 10000;

    var svg = d3.select("body").append("svg")
        .attr("width", w)
        .attr("height", h);

/*
    var line = d3.line()
            .x(function (d) {return projection([d.lon]);})
            .y(function (d) {return projection([d.lat]);})
    .curve(d3.curveBasis);

    var line = d3.line()
    .x(function(d){return projection(d[0].lon);})
    .y(function(d){return projection(d[0].lat);})
    .curve(d3.curveBasis);

/*ok line shows up but in wrong place
    var line = d3.line()
    .x(function(d) { return (d.lon); })
    .y(function(d) { return (d.lat); })
        .curve(d3.curveBasis);
*/

var line = d3.line()
    .x(function(d) { return (d.lon); })
    .y(function(d) { return (d.lat); })
    .curve(d3.curveBasis);


//original
/*
var line = d3.line()
.x(function(d){return projection(d)[0];})
.y(function(d){return projection(d)[1];})
.curve(d3.curveBasis);
*/
//

//bring in data
d3.queue()
    .defer(d3.json, "data/oceans.json")
    .defer(d3.csv, "data/speckCities.csv")
    .await(ready);

function ready (error, oceans, data){
    if (error) throw error;

    //console.log(data[0]);
    //console.log(data[0].lon);




//map
svg.selectAll("path")
        .data(oceans.features)
        .enter()
        .append("path")
        .attr("d", path)
        .style("fill", "#A8B2C3");

var linepath = svg.append("path")
  .datum(data)
  .attr("d", line)
    .attr('class', 'line');

    svg.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", "yellow")
         .style("stroke", "gray")
         .style("stroke-width", 0.25)
         .style("opacity", 0.75)
         .append("title")           //Simple tooltip
         .text(function(d) {
            return d.name ;
         });

    //




    //

    /*svg.selectAll(".point")
      .data(coordinates)
        .enter()
        .append("circle")
      .attr("r", 7)
      .attr("transform", function(d) { return "translate(" + projection(d) + ")"; });


var circle = svg.append("circle")
  .attr("r", 19)
  .attr("transform", "translate(" + projection(d) + ")");

/*
var pauseValues = {
        lastT: 0,
        currentT: 0
        };

function transition() {
  circle.transition()
      .duration(duration - (duration * pauseValues.lastT))
      .attrTween("transform", translateAlong(linepath.node()))
      .on("end", function(){
        pauseValues = {
          lastT: 0,
          currentT: 0
        };
        transition()
      });
}

function translateAlong(path) {
  var l = path.getTotalLength();
  return function(d, i, a) {
    return function(t) {
      t += pauseValues.lastT;
      var p = path.getPointAtLength(t * l);
      pauseValues.currentT = t;
      return "translate(" + p.x + "," + p.y + ")";
    };
  };
}

d3.select('button').on('click',function(d,i){
  var self = d3.select(this);
  if (self.text() == "Pause"){
        self.text('Play');
        circle.transition()
      .duration(0);
        setTimeout(function(){
            pauseValues.lastT = pauseValues.currentT;
        }, 100);
  }else{
    self.text('Pause');
    transition();
  }
});
*/
}

</script>
</body>
</html>

推荐答案

您没有投影线条:

var linepath = svg.append("path")
  .datum(data)
  .attr("d", line)
   .attr('class', 'line');

在这种情况下,您的geojson中的经度/纬度对将转换为直线像素坐标:

In this case your longitude/latitude pairs in your geojson are converted to straight pixel coordinates:

var line = d3.line()
    .x(function(d) { return (d.lon); })
    .y(function(d) { return (d.lat); })
    .curve(d3.curveBasis);

当svg坐标从左上角的[0,0]开始时,您的点似乎位于向东约10度(正经度),向北约50度(正纬度),这是您的第一个点该行从左侧出现10个像素,从顶部出现50个像素.另外,由于svg y值随向下移动而增加,而纬度值随向北移动(通常在地图上向上)而增加,因此,与点相比,您的线在y轴上也显示为倒转.

As svg coordinates start at [0,0] in the top left, and your points appear to be around 10 degrees east or so (positive longitude), and 50 degrees north or so (positive latitude), your first point in the line appears 10 pixels from the left and 50 pixels from the top. Also, because svg y values increase as one moves down, but latitude values increase as one moves north (typcally up on a map), your line also appears inverted on the y axis compared to your points.

您可以将线功能设置为使用投影来设置x和y点:

You could set your line function to use a projection to set the x and y points:

var line = d3.line()
    .x(function(d) { return projection([d.lon,d.lat])[0] ; })
    .y(function(d) { return projection([d.lon,d.lat])[1]; })
    .curve(d3.curveBasis);

您需要同时经度和纬度来投影一个点,因此投影函数会同时使用它们并返回x和y,因此返回[0]和[1],这就是为什么您注释掉的部分不这样做的原因工作

但这是不必要的,您可以将geojson直接传递到路径(与您对世界背景所做的一样),也就是说,如果您的数据在geojson中可用(尽管即时创建geojson并不困难) ):

But this is unnecessary, you can pass geojson straight to the path (the same as you do for the world background), that is if your data is available in geojson (though it is not hard to make a geojson on the fly):

var linepath = svg.append("path")
  .datum(data) // in geojson form
  .attr("d", path)  // use your path 
  .attr('class', 'line');

这比直线更精确-d3.line中直线之间的线段在直角坐标空间中是直的或遵循预定义的曲线. d3.geoPath遵循较大的圆距,因此点之间的线段遵循地球上最短的路径,这是一种更精确的表示,有时甚至认为其样式也不那么精确.

This is more accurate than a line - the segments between lines in a d3.line are straight or follow a predefined curve, in Cartesian coordinate space. A d3.geoPath follows great circle distance, so the segments between points follow the shortest path on the planet, a more accurate representation, thought at times perhaps, less stylistic.

要动态创建geojson,假设您的数据如下所示:[{lon:number,lat:number},{lon:number,lat:number}]您可以使用以下内容:

To create the geojson on the fly, assuming your data looks like: [{lon:number,lat:number},{lon:number,lat:number}] you could use something like:

var points = data.map(function(d) { return [d.lon,d.lat] })
var geojson = { "type": "LineString", "coordinates": points }

这篇关于d3线和csv数据在地图上的点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆