使用Google Map Api v.3使用GeoJson在折线上制作符号动画

时间:2016-05-19 07:05:27

标签: google-maps-api-3 geojson

我有这样的geojson:

    {
"type": "FeatureCollection",
"crs": { "type": "name", "properties": { "name": "urn:ogc:def:crs:OGC:1.3:CRS84" } },

"features": [
{ "type": "Feature", "properties": { "Name": "Saluran I", "descriptio": null, "timestamp": null, "begin": null, "end": null, "altitudeMo": null, "tessellate": 1, "extrude": -1, "visibility": -1, "drawOrder": null, "icon": null }, "geometry": { "type": "LineString", "coordinates": [ [ 115.16149264388849, -8.692345779607091 ], [ 115.1619799975747, -8.693099022961922 ], [ 115.1621209969948, -8.693450580043523 ], [ 115.1621893956145, -8.69367970180001 ], [ 115.1622369286341, -8.693885376054253 ], [ 115.16248624315379, -8.694125330077087 ], [ 115.1625293838875, -8.694297689361708 ], [ 115.1625662929434, -8.694480291402353 ], [ 115.1638244075253, -8.694489484612449 ] ] } },
{ "type": "Feature", "properties": { "Name": "Saluran II", "descriptio": null, "timestamp": null, "begin": null, "end": null, "altitudeMo": null, "tessellate": 1, "extrude": -1, "visibility": -1, "drawOrder": null, "icon": null }, "geometry": { "type": "LineString", "coordinates": [ [ 115.1647420393289, -8.691263798416188 ], [ 115.16480885306601, -8.691910749059817 ], [ 115.1648021389716, -8.692020041570267 ], [ 115.16476460026691, -8.692197857370241 ], [ 115.16467300953239, -8.692311184386924 ], [ 115.1645832229062, -8.692570845169653 ], [ 115.164590403574, -8.69280000074686 ], [ 115.1642184661912, -8.692878192437396 ], [ 115.16418831658579, -8.693471791565786 ], [ 115.16411080877791, -8.69417746825723 ], [ 115.1639500244154, -8.694469415766308 ], [ 115.1638498474275, -8.69450385891758 ], [ 115.1637726241196, -8.6949183073729 ], [ 115.1637482310352, -8.695106949243888 ], [ 115.16369576938609, -8.695516868583109 ], [ 115.1633930487843, -8.695552277605064 ], [ 115.1628619559151, -8.695616245099258 ], [ 115.1628453449146, -8.695861398016726 ], [ 115.1625531407406, -8.695981675836846 ], [ 115.1619167160671, -8.696110249672243 ], [ 115.1621001879372, -8.697348692504496 ], [ 115.1619454016469, -8.697429501488445 ] ] } },
{ "type": "Feature", "properties": { "Name": "Saluran III", "descriptio": null, "timestamp": null, "begin": null, "end": null, "altitudeMo": null, "tessellate": 1, "extrude": -1, "visibility": -1, "drawOrder": null, "icon": null }, "geometry": { "type": "LineString", "coordinates": [ [ 115.1649918428157, -8.698726927918452 ], [ 115.1647717936939, -8.698771893626452 ], [ 115.16464767674699, -8.698766178177538 ], [ 115.164531974608, -8.698766747854149 ], [ 115.1643076171094, -8.698759607942607 ], [ 115.1639182931609, -8.698808262913275 ], [ 115.1637251462856, -8.69887278452787 ], [ 115.1633890383243, -8.698973728970067 ], [ 115.1626822904817, -8.699201749498535 ], [ 115.1626359629325, -8.699082282748639 ], [ 115.1621957225977, -8.698410881596306 ], [ 115.16193358395429, -8.69743434218265 ] ] } }
]
}

我可以在我的地图上显示geojson,

    line.loadGeoJson(urlBase + 'peta/aliran.geojson');
    // styling features aliran
    line.setStyle(function(feature){
     return {
         strokeColor : '#0000FF',
         strokeWeight : 5,
         zIndex : 1
     } 
    });
   // set map;
   line.setMap(map);

但是当我想在线上设置符号动画时我有问题:https://developers.google.com/maps/documentation/javascript/examples/overlay-symbol-animate。有人能帮助我吗?

1 个答案:

答案 0 :(得分:1)

利用此related example (which animates a marker along a polyline from the directions service)中的代码为数据中某条折线上的符号设置动画:

proof of concept fiddle

代码段



var map;
var position;
var marker = null;
var polyline = null;
var poly2 = null;
var speed = 0.000005,
  wait = 1;
var infowindow = null;

var myPano;
var panoClient;
var nextPanoId;
var timerHandle = null;

var polyline;

function initialize() {
  map = new google.maps.Map(
    document.getElementById("map_canvas"), {
      center: new google.maps.LatLng(37.4419, -122.1419),
      zoom: 13,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });
  var bounds = new google.maps.LatLngBounds();
  map.data.addListener('addfeature', function(e) {
    processPoints(e.feature.getGeometry(), bounds.extend, bounds);
    if (e.feature.getGeometry().getType() == "LineString") {

      polyline = new google.maps.Polyline({
        map: map,
        path: e.feature.getGeometry().getArray(),
        strokeWeight: 5,
        strokeOpacity: 0.4,
        strokeColor: 'red'
      });
      marker = createMarker(polyline.getPath().getAt(0), "here", "marker text");
      setTimeout(startAnimation, 2000);

    }
    map.fitBounds(bounds);
  });
  // var line = google.maps.Data;
  map.data.addGeoJson(geoJson);
  // styling features aliran
  map.data.setStyle(function(feature) {
    return {
      strokeColor: '#0000FF',
      strokeWeight: 1,
      zIndex: 1
    }
  });
  // set map;
  map.data.setMap(map);
}
var step = 5; // metres
var tick = 100; // milliseconds
var eol;
var k = 0;
var stepnum = 0;
var speed = "";
var lastVertex = 1;


//=============== animation functions ======================
function updatePoly(d) {
  // Spawn a new polyline every 20 vertices, because updating a 100-vertex poly is too slow
  if (poly2.getPath().getLength() > 20) {
    poly2 = new google.maps.Polyline([polyline.getPath().getAt(lastVertex - 1)]);
  }

  if (polyline.GetIndexAtDistance(d) < lastVertex + 2) {
    if (poly2.getPath().getLength() > 1) {
      poly2.getPath().removeAt(poly2.getPath().getLength() - 1)
    }
    poly2.getPath().insertAt(poly2.getPath().getLength(), polyline.GetPointAtDistance(d));
  } else {
    poly2.getPath().insertAt(poly2.getPath().getLength(), polyline.getPath().getAt(polyline.getPath().getLength() - 1));
  }
}


function animate(d) {
  if (d > eol) {
    map.panTo(endLocation.latlng);
    marker.setPosition(endLocation.latlng);
    return;
  }
  var p = polyline.GetPointAtDistance(d);
  map.panTo(p);
  marker.setPosition(p);
  updatePoly(d);
  timerHandle = setTimeout("animate(" + (d + step) + ")", tick);
}


function startAnimation() {
  if (timerHandle) clearTimeout(timerHandle);
  eol = google.maps.geometry.spherical.computeLength(polyline.getPath());
  map.setCenter(polyline.getPath().getAt(0));
  poly2 = new google.maps.Polyline({
    path: [polyline.getPath().getAt(0)],
    strokeColor: "#0000FF",
    strokeWeight: 10
  });
  setTimeout("animate(0)", tick); // Allow time for the initial map display
}




function processPoints(geometry, callback, thisArg) {
  if (geometry instanceof google.maps.LatLng) {
    callback.call(thisArg, geometry);
  } else if (geometry instanceof google.maps.Data.Point) {
    callback.call(thisArg, geometry.get());
  } else {
    geometry.getArray().forEach(function(g) {
      processPoints(g, callback, thisArg);
    });
  }
}

// ==================================================
function createMarker(latlng, label, html) {
  var contentString = '<b>' + label + '</b><br>' + html;
  var marker = new google.maps.Marker({
    position: latlng,
    map: map,
    title: label,
    icon: {
      path: google.maps.SymbolPath.CIRCLE,
      scale: 8,
      strokeColor: '#393'
    },
    zIndex: Math.round(latlng.lat() * -100000) << 5
  });

  marker.myname = label;
  // gmarkers.push(marker);

  google.maps.event.addListener(marker, 'click', function() {
    infowindow.setContent(contentString);
    infowindow.open(map, marker);
  });
  return marker;
}

google.maps.event.addDomListener(window, "load", initialize);

var geoJson = {
  "type": "FeatureCollection",
  "crs": {
    "type": "name",
    "properties": {
      "name": "urn:ogc:def:crs:OGC:1.3:CRS84"
    }
  },

  "features": [{
    "type": "Feature",
    "properties": {
      "Name": "Saluran II",
      "descriptio": null,
      "timestamp": null,
      "begin": null,
      "end": null,
      "altitudeMo": null,
      "tessellate": 1,
      "extrude": -1,
      "visibility": -1,
      "drawOrder": null,
      "icon": null
    },
    "geometry": {
      "type": "LineString",
      "coordinates": [
        [115.1647420393289, -8.691263798416188],
        [115.16480885306601, -8.691910749059817],
        [115.1648021389716, -8.692020041570267],
        [115.16476460026691, -8.692197857370241],
        [115.16467300953239, -8.692311184386924],
        [115.1645832229062, -8.692570845169653],
        [115.164590403574, -8.69280000074686],
        [115.1642184661912, -8.692878192437396],
        [115.16418831658579, -8.693471791565786],
        [115.16411080877791, -8.69417746825723],
        [115.1639500244154, -8.694469415766308],
        [115.1638498474275, -8.69450385891758],
        [115.1637726241196, -8.6949183073729],
        [115.1637482310352, -8.695106949243888],
        [115.16369576938609, -8.695516868583109],
        [115.1633930487843, -8.695552277605064],
        [115.1628619559151, -8.695616245099258],
        [115.1628453449146, -8.695861398016726],
        [115.1625531407406, -8.695981675836846],
        [115.1619167160671, -8.696110249672243],
        [115.1621001879372, -8.697348692504496],
        [115.1619454016469, -8.697429501488445]
      ]
    }
  }]
};

/*********************************************************************\
*                                                                     *
* epolys.js                                          by Mike Williams *
* updated to API v3                                  by Larry Ross    *
*                                                                     *
* A Google Maps API Extension                                         *
*                                                                     *
* Adds various Methods to google.maps.Polygon and google.maps.Polyline *
*                                                                     *
* .Contains(latlng) returns true is the poly contains the specified   *
*                   GLatLng                                           *
*                                                                     *
* .Area()           returns the approximate area of a poly that is    *
*                   not self-intersecting                             *
*                                                                     *
* .Distance()       returns the length of the poly path               *
*                                                                     *
* .Bounds()         returns a GLatLngBounds that bounds the poly      *
*                                                                     *
* .GetPointAtDistance() returns a GLatLng at the specified distance   *
*                   along the path.                                   *
*                   The distance is specified in metres               *
*                   Reurns null if the path is shorter than that      *
*                                                                     *
* .GetPointsAtDistance() returns an array of GLatLngs at the          *
*                   specified interval along the path.                *
*                   The distance is specified in metres               *
*                                                                     *
* .GetIndexAtDistance() returns the vertex number at the specified    *
*                   distance along the path.                          *
*                   The distance is specified in metres               *
*                   Returns null if the path is shorter than that      *
*                                                                     *
* .Bearing(v1?,v2?) returns the bearing between two vertices          *
*                   if v1 is null, returns bearing from first to last *
*                   if v2 is null, returns bearing from v1 to next    *
*                                                                     *
*                                                                     *
***********************************************************************
*                                                                     *
*   This Javascript is provided by Mike Williams                      *
*   Blackpool Community Church Javascript Team                        *
*   http://www.blackpoolchurch.org/                                   *
*   http://econym.org.uk/gmap/                                        *
*                                                                     *
*   This work is licenced under a Creative Commons Licence            *
*   http://creativecommons.org/licenses/by/2.0/uk/                    *
*                                                                     *
***********************************************************************
*                                                                     *
* Version 1.1       6-Jun-2007                                        *
* Version 1.2       1-Jul-2007 - fix: Bounds was omitting vertex zero *
*                                add: Bearing                         *
* Version 1.3       28-Nov-2008  add: GetPointsAtDistance()           *
* Version 1.4       12-Jan-2009  fix: GetPointsAtDistance()           *
* Version 3.0       11-Aug-2010  update to v3                         *
*                                                                     *
\*********************************************************************/
// === A method which returns a GLatLng of a point a given distance along the path ===
// === Returns null if the path is shorter than the specified distance ===
google.maps.Polyline.prototype.GetPointAtDistance = function(metres) {
    // some awkward special cases
    if (metres == 0) return this.getPath().getAt(0);
    if (metres < 0) return null;
    if (this.getPath().getLength() < 2) return null;
    var dist = 0;
    var olddist = 0;
    for (var i = 1;
      (i < this.getPath().getLength() && dist < metres); i++) {
      olddist = dist;
      dist += google.maps.geometry.spherical.computeDistanceBetween(this.getPath().getAt(i), this.getPath().getAt(i - 1));
    }
    if (dist < metres) {
      return null;
    }
    var p1 = this.getPath().getAt(i - 2);
    var p2 = this.getPath().getAt(i - 1);
    var m = (metres - olddist) / (dist - olddist);
    return new google.maps.LatLng(p1.lat() + (p2.lat() - p1.lat()) * m, p1.lng() + (p2.lng() - p1.lng()) * m);
  }
  // === A method which returns the Vertex number at a given distance along the path ===
  // === Returns null if the path is shorter than the specified distance ===
google.maps.Polyline.prototype.GetIndexAtDistance = function(metres) {
  // some awkward special cases
  if (metres == 0) return this.getPath().getAt(0);
  if (metres < 0) return null;
  var dist = 0;
  var olddist = 0;
  for (var i = 1;
    (i < this.getPath().getLength() && dist < metres); i++) {
    olddist = dist;
    dist += google.maps.geometry.spherical.computeDistanceBetween(this.getPath().getAt(i), this.getPath().getAt(i - 1));
  }
  if (dist < metres) {
    return null;
  }
  return i;
}
&#13;
html,
body,
#map_canvas {
  height: 100%;
  width: 100%;
  margin: 0px;
  padding: 0px
}
&#13;
<script src="https://maps.googleapis.com/maps/api/js?libraries=geometry"></script>
<input type="button" value="restart animation" onclick="startAnimation()" />
<div id="map_canvas"></div>
&#13;
&#13;
&#13;