【问题标题】:Using D3-Geo to plot a shape使用 D3-Geo 绘制形状
【发布时间】:2020-07-14 07:22:46
【问题描述】:

我正在使用d3-geo 包在经纬度空间中绘制点和形状。我想绘制一个以点为中心的简单多边形、三角形、正方形、星形等。如果可能的话,我还想在给定的 [lat,lon] 处绘制文本。

我目前正在运行以下代码,并在给定坐标 [-40.5, 65.5] 处绘制一个环。但是,我希望能够在此位置定义不同的形状,是否有一种简单的方法可以做到这一点而无需自己手动定义形状?有一个空的“属性”字段,我找不到任何可以使用的文档?到目前为止,D3-geo 文档和谷歌搜索已经产生了 zilch。

let geoGenerator = geoPath()
  .projection(projection)
  .pointRadius(4)
  .context(context); //2d Canvas contect

context.beginPath();
geoGenerator({
  type: "Feature",
  geometry: {
    type: "Point",
    coordinates: [-40.5, 65.5]
  },
  properties: {}
});
context.stroke();

【问题讨论】:

    标签: javascript d3.js


    【解决方案1】:

    Geojson 在其规范中没有任何属性来指定应绘制的符号类型(符号形状、颜色、大小等)。 Geojson 仅在地理坐标中指定绘制对象的几何形状(点、线、多边形等)。

    当然,您可以使用 geojson 功能的 properties 属性来保存符号数据,除非您自己构建该功能,否则它对渲染功能没有影响。

    虽然 geojson 没有任何符号规范,但 D3 中的 geoPath 生成器让您指定绘制符号的一部分:点的半径(否则点是无量纲的)。但是,除此之外,d3-geo 不支持绘制特定符号,它只能投影几何体。

    要在特定地理坐标处绘制符号,您需要投影坐标 (projection([longitude,latitude]))。现在您有了像素值坐标,您可以使用该坐标来绘制符号。您不想尝试在地理坐标中绘制符号,因为它不可扩展且依赖于投影。

    这是一个使用 d3-symbol 的简单实现(我没有画出世界其他地方,只是两点,但它们被正确投影):

    var context = d3.select("canvas").node().getContext("2d");
    
    var points = [[-136,63],[-123,50]];
    
    var projection = d3.geoMercator();
    
    var shape = d3.symbol()
         .type(d3.symbolWye)
         .context(context)
         .size(200);
    
    var shapey = function(lonlat) {
       // Get xy Data
       var xy = projection(lonlat);
       // save without translation.
       context.save(); 
       // position symbol:
       context.translate(...xy);
       // Draw symbol:
       context.beginPath();   
       shape();
       context.fill();
       // Remove translation:
       context.restore();
    }
    
    
    points.forEach(shapey);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <canvas width="500" height="300"></canvas>

    当然你也可以指定自己的形状,这是一个简单的正方形实现:

    var context = d3.select("canvas").node().getContext("2d");
    
    var points = [[-136,63],[-123,50]];
    
    var projection = d3.geoMercator();
    
    var shape = function(xy) {
      var offset = 10;
      var x = xy[0];
      var y = xy[1];
      context.beginPath();
      // draw a sqaure:
      context.moveTo(x-offset,y-offset);
      context.lineTo(x-offset,y+offset);
      context.lineTo(x+offset,y+offset);
      context.lineTo(x+offset,y-offset);
      context.lineTo(x-offset,y-offset);
      context.fill();
      context.strokeStyle = "steelblue";
      context.lineWidth = 5;
      context.lineCap = "square"
      context.stroke();
    }
    
    var shapey = function(lonlat) {
       // Get xy Data
       var xy = projection(lonlat);
       // save without translation.
       shape(xy);
    
    }
    
    
    points.forEach(shapey);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
    <canvas width="500" height="300"></canvas>

    当然,您可以对这些基本功能有更多的了解,但为了演示的目的,它们应该足够了。

    【讨论】:

    • 感谢@Andrew Reid,正是我想要的。
    猜你喜欢
    • 2018-04-24
    • 2018-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多