D3 +谷歌地图+多点路径

时间:2014-01-23 14:29:24

标签: javascript google-maps d3.js

我在Google地图上绘制点(到目前为止一直很好),然后根据基础数据中的点顺序绘制每个点之间的一条线(不太好)。就像一条小路或路线。

与我见过的一些例子不同,我的数据不是GeoJSON格式,如果可能的话,我会真的喜欢这样做。我试图调整发布herehere的示例,但没有成功。

我的结果最终没有绘制任何线条,我无法判断这是因为投影错误还是其他与D3相关的语法。我试图通过console.log()语句进行调试,但我每周都在进行GIS预测。

以下是绘制点的代码

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no"/>
<script type="text/javascript" src="https://maps.google.com/maps/api/js?sensor=true"></script>
<script src="../js/d3.v3.min.js"></script>
<style type="text/css">

        html, body, #map {
          width: 100%;
          height: 100%;
          margin: 0;
          padding: 0;
        }

        .markers {
          position: absolute;
        }

        svg.pts {
          position: absolute;
        }

        .markers border {
          position: absolute;
         stroke: black;
         stroke-width: 2px;
        }

        .markers svg.pts {
          width: 60px;
          height: 20px;
          padding-right: 100px;
          font: 10px sans-serif;
        }

        .markers circle {
          fill: brown;
          stroke: black;
          stroke-width: 1.5px;
        }


        .SvgOverlay path {
            stroke: Orange;
            stroke-width: 2px;
            fill: Orange;
            fill-opacity: .3;
        }

            </style>
          </head>
          <body>
            <div id="map"></div>
            <script type="text/javascript">

var map = new google.maps.Map(d3.select("#map").node(), {
  zoom: 15,
  center: new google.maps.LatLng(29.371397, -81.54938), //N/S E/W
  mapTypeId: google.maps.MapTypeId.ROADMAP 
});

        var data =      [ //note this is not in GeoJSON format
{name:"pt1",lng:-81.55082967,lat:29.374915304},
{name:"pt2",lng:-81.55211713,lat:29.373504039},
{name:"pt3",lng:-81.5842252,lat:29.417969924},
{name:"pt4",lng:-81.55230021,lat:29.374245073},
{name:"pt5",lng:-81.55115,lat:29.37263},
{name:"pt6",lng:-81.58737814,lat:29.358476912},
{name:"pt7",lng:-81.59230268,lat:29.359308171},
{name:"pt8",lng:-81.58783883,lat:29.356449048},
{name:"pt9",lng:-81.58189168,lat:29.420264027},
{name:"pt10",lng:-81.58288,lat:29.4202},
{name:"pt11",lng:-81.56079477,lat:29.359527893},
{name:"pt12",lng:-81.55861145,lat:29.356670068},
{name:"pt13",lng:-81.57961314,lat:29.420893275},
{name:"pt14",lng:-81.579302,lat:29.419368},
{name:"pt15",lng:-81.55979967,lat:29.359768002},
{name:"pt16",lng:-81.55823261,lat:29.36122515},
{name:"pt17",lng:-81.58189168,lat:29.420264027},
{name:"pt18",lng:-81.57997524,lat:29.421120323},
{name:"pt19",lng:-81.58148399,lat:29.420030491},
{name:"pt20",lng:-81.57839075,lat:29.420766158},
{name:"pt21",lng:-81.57982489,lat:29.42002304},
{name:"pt22",lng:-81.580266,lat:29.420212},
{name:"pt23",lng:-81.5820392,lat:29.42048164},
{name:"pt24",lng:-81.57894731,lat:29.420509033},
{name:"pt25",lng:-81.57819629,lat:29.418834169}
];


        var overlay = new google.maps.OverlayView();

        overlay.onAdd = function() {
          var layer = d3.select(this.getPanes().overlayLayer).append("div")
                .attr("height", "100%")
                .attr("width", "100%")
                .attr("class", "markers")
                .attr("id", "layer");

          layer[0][0].style.width = "1366px";
          layer[0][0].parentNode.style.width = "100%";
          layer[0][0].parentNode.style.height = "100%";
          layer[0][0].parentNode.parentNode.style.width = "100%";
          layer[0][0].parentNode.parentNode.style.height = "100%";
          layer[0][0].parentNode.parentNode.parentNode.style.width = "100%";
          layer[0][0].parentNode.parentNode.parentNode.style.height = "100%";
          layer[0][0].parentNode.parentNode.parentNode.parentNode.style.width = "100%";
          layer[0][0].parentNode.parentNode.parentNode.parentNode.style.height = "100%";

          // Add points
          overlay.draw = function() {
            var projection = this.getProjection(),
                padding = 10;

            var point = layer.selectAll("svg")
                .data( data )
                .each(transform) // update existing markers
              .enter().append("svg:svg")
                .each(transform)
                .attr("class", "point pts")
        // Add marker on points
            point.append("svg:circle")
                .attr("r", 4.5)
                .attr("cx", padding )
                .attr("cy", padding );

            // Add a label on points
            point.append("svg:text")
                .attr("x", padding + 7)
                .attr("y", padding)
                .attr("dy", ".31em")
                .text( function(d) { 
                  return d.name; }
                );
            //Here is where I'd like to add lines connecting the points, in order
            //of appearance in the data object


            function _projection( lat, lng ) {
              e = new google.maps.LatLng( lat, lng );
              e = projection.fromLatLngToDivPixel(e);
              return [ e.x - padding, e.y - padding]
              // return [ e.x, e.y ]
            }

            function transform(d) {
              //console.log(d);
              e = _projection( d.lat, d.lng )
              return d3.select(this)
                  .style("left", e[0] + "px")
                  .style("top", e[1] + "px");
            }


          };
        };

        // Bind overlay to the map…
        overlay.setMap(map);

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

here is a JSFiddle

非常感谢建议通过所呈现的数据对象添加路径。

1 个答案:

答案 0 :(得分:2)

好的,所以我看了一下你的代码并稍微重构了一下。但这是在点之间绘制的路径的基本工作版本:http://jsfiddle.net/AJvt4/3/。但有一点需要注意,那就是当地图平移时,overlayPane不会扩展。我对谷歌地图不太熟悉,所以不确定我能帮到那里多少钱。以下是对所做更改的解释:

首先,我创建了一个包含svg来容纳onAdd事件中的所有d3元素:

var svg = layer.append('svg')
    .attr('x', 0)
    .attr('y', 0)

同样在onAdd事件中,我添加了一个d3路径生成器(您可以阅读更多here):

var lineFn = d3.svg.line()
    .x(function (d) {
    e = _projection(d.lat, d.lng);
    return e[0] + padding
})
    .y(function (d) {
    e = _projection(d.lat, d.lng);
    return e[1] + padding
})

为了实际画线,我在add事件处理程序中添加了这个:

var line = svg.selectAll('.path').data([data])
    line.enter().append('path')
    line.attr('class', 'path')
        .attr('d', lineFn)

注意数据周围的数组([data])非常重要。这是因为d3需要一个数组数组,每个内部数组都指向一行。这样可以更容易地绘制多条线。在你的情况下,只有一行。

您会注意到其他一些更改,使代码更加d3-esque。希望有助于您入门!