javascript - D3 + 谷歌地图 + 多点路径

标签 javascript google-maps d3.js

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

与我见过的少数这样做的示例不同,我的数据不是 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

非常感谢关于通过数据对象添加路径的建议。

最佳答案

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

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

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。希望这能帮助您入门!

关于javascript - D3 + 谷歌地图 + 多点路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21310986/

相关文章:

javascript - 静音自动播放视频显示错误 : play() failed because the user didn't interact with the document first.

javascript - 单击按钮时有没有办法检查 Div 内的图像?

javascript - 查找附加事件的元素

javascript - 更改 Google map 中的颜色(自定义)

javascript - 当 Google map 生成事件时

javascript - jsPlumb:无法在充当 jsPlumb 源/目标的 div 内的 div 上单击()

php - 用于获取 Google for Business 的所有评论和评级的 API

javascript - 在 D3.js 中的动态 forcelayout 图中显示节点标签

javascript - 如何 reshape 现有 JSON 以适应 Highcharts

javascript - 可折叠缩进树的初始状态