How do i animate the polyline like uber app in android and ios

6934
5
03-26-2018 08:08 PM
AsifIsmail
New Contributor III

i have polyline set from point A to point B to which i need to create an animation as we see in uber app (trail animation) between the points something like this

0 Kudos
5 Replies
XanderBakker
Esri Esteemed Contributor

You haven't mentioned what software you want to show the animation in, but if you look at the Road Map for ArcGIS Pro: https://community.esri.com/community/gis/applications/arcgis-pro/blog/2018/02/02/arcgis-pro-roadmap  you will see that animated symbols are planned to release in the Mid Term. You can create animated point symbols (not what you are looking for) as described here: Bring Your Points to Life with GIF Symbols | ArcGIS Blog  and use GeoEvent Server | ArcGIS Enterprise to simulate movement along a route. Otherwise you will probably end up programming this functionality.

0 Kudos
AsifIsmail
New Contributor III

I use Android studio and xcode with their native sdk to develop app for

esri.

I don't want to animate the points but the path in which polyline is drawn

0 Kudos
AbdulKhan
New Contributor II

Asif - did you figure this out? I have the same issue - want to animate the polyline - but in javascript

0 Kudos
Kalyan_SinghRathore
New Contributor II

Anybody figured this out ? I need to animate the polyline between two point like growing lines towards destination. (In ArcGis 4.11 Javascript)

0 Kudos
MartinCalcagno
New Contributor

Hi, I was able to do this on Android using Esri's SDK (version 100.6.0)

The route I have was from calling

routeTask.solveRouteAsync(routeParameters);


After I had the route (a Graphic object), I added it to the graphics on the graphics overlay

graphicsOverlay.getGraphics().add(routeGraphic)

I got all the graphics from the graphicsOverlay and looked for this route (I know this is not even close to be a good idea, but it's the only one I had).

for (int i = 0; i < graphicsOverlay.getGraphics().size(); i++) {
   Graphic g = graphicsOverlay.getGraphics().get(i);
   if (g.getGeometry() != null && g.getGeometry().getInternal() != null &&
      g.getGeometry().getInternal().w() != null && !g.getGeometry().getInternal().w().equals("")) {
      Path path = new Gson().fromJson(g.getGeometry().getInternal().w(), Path.class);
      if (path.getPaths() != null && path.getPaths().length > 0) {
         Log.d("Graphic " + i, ", " + g.getGeometry().getInternal().w());
         List<Marker> points = path.getPoints();
         Log.d("path.getPoints", " size " + points.size());
         Path.pointsInPath(new ArrayList<>(points), 50, 1); // speed: 50km/h, refresh rate: 1 per second
      }
   }
}

The Path class was needed to parse the JSon I got from

g.getGeometry().getInternal().w()

In this class the important atritube is

private double[][][] paths

and the important method is getPoints()

public List<Marker> getPoints() {
   List<Marker> list = new ArrayList<>();
   list.add(new Marker(getPaths()[0][0][0], getPaths()[0][0][1], Marker.REPRESENTATION_WGS84));

   for (int i = 0; i < getPaths().length; i++) {
      for (int j = 0; j < getPaths().length; j++) {
         if (j > 0) {
            list.add(new Marker(getPaths()[0], getPaths()[1], Marker.REPRESENTATION_WGS84));
         }
      }
   }
   return list;
}


This Method joins the segments of the route on the map (as the method: g.getGeometry().getInternal().w() returns a group of segments of the route that ended and started one after the other, I just ignored the first point of each route, except for the first route, to get a succession of points that forms the "real" route I wanted), you may have to change this method acording to your problem.

The Marker class is just like Point from Esri, it has longitud, latitude and its representation (wgs84 in this case)

pointsInPath is a method that shows the current position of the uber, acroding to a speed (50km/h) and a refresh rate (1 per second)

public static List<Marker> pointsInPath(List<Marker> list, double speed, double refreshRate) {
   double distRecorrida = (speed / 3600) * refreshRate;
   return Path.nextPoint(list, distRecorrida, distRecorrida);
}

private static List<Marker> nextPoint(List<Marker> list, double distAcumulada, double distPorSalto) {
   if (list == null || list.size() == 0) {
      return null;
   } else if (list.size() == 1) {
      return list;
   } else {
      Marker org = list.get(0);
      Marker dst = list.get(1);
      double distPuntos = Marker.LotLong2Km(org, dst);
      if (distPuntos < distAcumulada) {
         list.remove(0);
         return nextPoint(list,distAcumulada - distPuntos, distPorSalto);
      } else if (distPuntos > distAcumulada) {
         double ratio = distAcumulada / distPuntos;
         double newLon = org.lon - (org.lon - dst.lon) * ratio;
         double newLat = org.lat - (org.lat - dst.lat) * ratio;
         Marker newMarker = new Marker(newLon, newLat, Marker.REPRESENTATION_WGS84);
         List<Marker> result = new ArrayList<>();
         result.add(newMarker);
         list.remove(0);
         list.add(0, newMarker);
         List<Marker> res = nextPoint(list, distPorSalto, distPorSalto);
         if (res != null) {
            result.addAll(res);
         }
         return result;
      } else {
         List<Marker> result = new ArrayList<>();
         result.add(list.get(1));
         list.remove(0);
         List<Marker> res = nextPoint(list, distPorSalto, distPorSalto);
         if (res != null) {
            result.addAll(res);
         }
         return result;
      }
   }
}

0 Kudos