How to animate graphic from one Location to another.

4306
8
Jump to solution
05-09-2017 12:04 AM
KrishV
by
Occasional Contributor III

I have tried to animate graphic from one location to another as shown in below code:

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    
    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
    <title>Animate Graphic</title>

    <link rel="stylesheet" href="https://js.arcgis.com/3.20/esri/css/esri.css">

    <style>
      #info {
        top: 20px;
        color: #444;
        height: auto;
        font-family: arial;
        right: 20px;
        margin: 5px;
        padding: 10px;
        position: absolute;
        width: 115px;
        z-index: 40;
        border: solid 2px #666;
        border-radius: 4px;
        background-color: #fff;
      }
      html, body, #mapDiv {
        padding:0;
        margin:0;
        height:100%;
      }
      button {
        display: block;
      }
    </style>

    <script src="https://js.arcgis.com/3.20/"></script>
    <script>
      var map, tb;

      require([
        "esri/map", "esri/toolbars/draw",
        "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
        "esri/symbols/PictureFillSymbol", "esri/symbols/CartographicLineSymbol", 
        "esri/graphic", "dojox/gfx/fx","dojo/_base/lang",
        "esri/Color", "dojo/dom", "dojo/on", "dojo/domReady!"
      ], function(
        Map, Draw,
        SimpleMarkerSymbol, SimpleLineSymbol,
        PictureFillSymbol, CartographicLineSymbol, 
        Graphic, fx, lang,
        Color, dom, on
      ) {
        map = new Map("mapDiv", {
          basemap: "streets",
          center: [-25.312, 34.307],
          zoom: 3
        });
        map.on("load", initToolbar);

        var markerSymbol = new SimpleMarkerSymbol();
        markerSymbol.setPath("M16,4.938c-7.732,0-14,4.701-14,10.5c0,1.981,0.741,3.833,2.016,5.414L2,25.272l5.613-1.44c2.339,1.316,5.237,2.106,8.387,2.106c7.732,0,14-4.701,14-10.5S23.732,4.938,16,4.938zM16.868,21.375h-1.969v-1.889h1.969V21.375zM16.772,18.094h-1.777l-0.176-8.083h2.113L16.772,18.094z");
        markerSymbol.setColor(new Color("#00FFFF"));
        

        function initToolbar() {
          tb = new Draw(map);
          tb.on("draw-end", addGraphic);

          // event delegation so a click handler is not
          // needed for each individual button
          on(dom.byId("info"), "click", function(evt) {
            if ( evt.target.id === "info" ) {
              return;
            }
            var tool = evt.target.id.toLowerCase();
            map.disableMapNavigation();
            tb.activate(tool);
          });
        }

        function addGraphic(evt) {
          //deactivate the toolbar and clear existing graphics 
          tb.deactivate(); 
          //map.enableMapNavigation();

         
          var symbol;
          if ( evt.geometry.type === "point") {
            symbol = markerSymbol;
           
                  var g=new Graphic(evt.geometry, symbol);
            map.graphics.add(g);
          
             setTimeout(lang.partial(function(animateMe) {
             var shape = animateMe.getDojoShape();
      
            var sp1 = map.toScreen(evt.geometry);

             fx.animateTransform({
                                  duration: 1200,
                                  shape: shape,
                                  transform: [{ name: "translate", start:[sp1.x,sp1.y], end:[sp1.x+50,sp1.y] }]}).play();
             }, g), 0);      
         }
        }
        
      });
    </script>
  </head>
  
  <body>
    
    <div id="info">
      <div>Select and draw on map to add graphic</div>
      <button id="Point">Point</button>
    </div>

    <div id="mapDiv"></div>

  </body>
</html>
‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

Animation function is working but graphic moves to different screen coordinates. Please suggest.

Regards,

Krish

Tags (2)
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Krish,

   The issue you are having now is that you are setting the animation start and end values the way you were before and I added the "original" property to the animation which mean use the shapes original coords and add the end values to the start original (0,0).

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
  <title></title>
  <link rel="stylesheet" href="https://js.arcgis.com/3.20/esri/css/esri.css">
  <style>
    html,
    body,
    #mapDiv {
      height: 100%;
      width: 100%;
      margin: 0;
      padding: 0;
    }
  </style>

  <script src="https://js.arcgis.com/3.20/"></script>
  <script>
    var map;
    require(["esri/map", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
        "esri/graphic", "dojox/gfx/fx", "dojo/_base/lang", "esri/Color", "dojo/dom", "esri/layers/GraphicsLayer",
        "dojo/on", "esri/geometry/ScreenPoint", "esri/geometry/Point", "esri/geometry/Polyline",
        "dojo/domReady!"
      ],
      function(Map, SimpleMarkerSymbol, SimpleLineSymbol,
        Graphic, fx, lang, Color, dom, GraphicsLayer,
        on, ScreenPoint, Point, Polyline) {
        var options = {
          basemap: "gray",
          center: [-29.88, 21.86133],
          zoom: 3
        };

        map = new Map("mapDiv", options);

        var linepath = [
          [-29.88231249999835, 21.861337104185896],
          [-29.706531249998385, 23.64436466438422],
          [-26.89403124999913, 29.152009189365007],
          [-25.4877812499995, 31.57838706044446],
          [-22.85106250000021, 34.08891708698886],
          [-19.862781250001014, 36.66827922896022],
          [-18.104968750001476, 37.787943753057206],
          [-14.765125000002355, 39.300164419151855],
          [-12.655750000002914, 39.97698664383719],
          [-10.370593750003529, 40.64717142579546],
          [-8.085437500004144, 41.178522893330914],
          [-4.218250000005169, 41.574231022027256],
          [0.7036249999935258, 41.836698107532534],
          [4.746593749992446, 41.836698107532534],
          [9.316906249991233, 41.836698107532534],
          [12.48096874999041, 41.836698107532534],
          [12.8325312499903, 41.836698107532534],
        ];

        var sls = new SimpleLineSymbol(
          SimpleLineSymbol.STYLE_DASH,
          new Color([255, 0, 0]),
          3
        );
        var pl = new Polyline({"paths": [linepath], "spatialReference":{"wkid":4326}});
        var vechPath = new Graphic(pl, sls);

        var markerSymbol = new SimpleMarkerSymbol();
        markerSymbol.setPath(
          "M16,4.938c-7.732,0-14,4.701-14,10.5c0,1.981,0.741,3.833,2.016,5.414L2,25.272l5.613-1.44c2.339,1.316,5.237,2.106,8.387,2.106c7.732,0,14-4.701,14-10.5S23.732,4.938,16,4.938zM16.868,21.375h-1.969v-1.889h1.969V21.375zM16.772,18.094h-1.777l-0.176-8.083h2.113L16.772,18.094z"
        );
        markerSymbol.setColor(new Color("#00FFFF"));

        var gLayerVehicle = new GraphicsLayer({
          "id": "Vehicle"
        });
        var gLayerVehiclePath = new GraphicsLayer({
          "id": "VehiclePath"
        });

        map.addLayers([gLayerVehiclePath, gLayerVehicle]);
        gLayerVehiclePath.add(vechPath);

        var myInterval = setInterval(test, 3000);
        var counter = 0;

        function test() {
          gLayerVehicle.clear();
          var p1 = new Point(linepath[counter]);
          var p2 = new Point(linepath[counter + 1]);
          var pt1Graphic = new Graphic(p1, markerSymbol);

          gLayerVehicle.add(pt1Graphic);

          var shape = pt1Graphic.getShape();
          console.info(shape.getTransform());
          var sp1 = map.toScreen(p1);
          var sp2 = map.toScreen(p2);

          var mp1 = map.toMap(new ScreenPoint(sp2.x, sp2.y));

          fx.animateTransform({
            duration: 1200,
            shape: shape,
            transform: [{
                name: "translate",
                start: [0,0],
                end: [sp2.x - sp1.x, sp2.y - sp1.y]
              },
              {name: "original"}
            ],
            onEnd: lang.hitch(this, function() {
              pt1Graphic.setGeometry(mp1);
            })
          }).play();
          counter++;
          if (counter >= linepath.length - 1) {
            clearInterval(myInterval);
          }
        }
      }
    );
  </script>
</head>

<body>
  <div id="mapDiv"></div>
</body>

</html>

View solution in original post

8 Replies
RobertScheitlin__GISP
MVP Emeritus

Krish,

   You need to account for the height of the SVG in your transform:

transform: [{
  name: "translate",
  start: [sp1.x, (sp1.y - shape.bbox.b)],
  end: [sp1.x + 50, (sp1.y - shape.bbox.b)]
}]
KrishV
by
Occasional Contributor III

Hi Robert,

Thanks for your quick response!

I have tried above code and observed when I pan on map and create point, graphic moves to different screen coordinates.

Please suggest how to achieve this.

Regards,

Krish

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Krish,

   That is because you are not updating the points geometry to the new MAP coordinates after the animation of the points screen coordinates are done. Here is your code updated:

<!DOCTYPE html>
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
  <title>Animate Graphic</title>
  <link rel="stylesheet" href="https://js.arcgis.com/3.20/esri/css/esri.css">

  <style>
    #info {
      top: 20px;
      color: #444;
      height: auto;
      font-family: arial;
      right: 20px;
      margin: 5px;
      padding: 10px;
      position: absolute;
      width: 115px;
      z-index: 40;
      border: solid 2px #666;
      border-radius: 4px;
      background-color: #fff;
    }

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

    button {
      display: block;
    }
  </style>

  <script src="https://js.arcgis.com/3.20/"></script>
  <script>
    var map, tb;
    require([
      "esri/map", "esri/toolbars/draw",
      "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
      "esri/symbols/PictureFillSymbol", "esri/symbols/CartographicLineSymbol",
      "esri/graphic", "dojox/gfx/fx", "dojo/_base/lang",
      "esri/Color", "dojo/dom", "dojo/on", "esri/geometry/ScreenPoint",
      "dojo/domReady!"
    ], function(
      Map, Draw,
      SimpleMarkerSymbol, SimpleLineSymbol,
      PictureFillSymbol, CartographicLineSymbol,
      Graphic, fx, lang,
      Color, dom, on, ScreenPoint
    ) {
      map = new Map("mapDiv", {
        basemap: "streets",
        center: [-25.312, 34.307],
        zoom: 3
      });
      map.on("load", initToolbar);

      var markerSymbol = new SimpleMarkerSymbol();
      markerSymbol.setPath(
        "M16,4.938c-7.732,0-14,4.701-14,10.5c0,1.981,0.741,3.833,2.016,5.414L2,25.272l5.613-1.44c2.339,1.316,5.237,2.106,8.387,2.106c7.732,0,14-4.701,14-10.5S23.732,4.938,16,4.938zM16.868,21.375h-1.969v-1.889h1.969V21.375zM16.772,18.094h-1.777l-0.176-8.083h2.113L16.772,18.094z"
      );
      markerSymbol.setColor(new Color("#00FFFF"));

      function initToolbar() {
        tb = new Draw(map);
        tb.on("draw-end", addGraphic);
        // event delegation so a click handler is not
        // needed for each individual button
        on(dom.byId("info"), "click", function(evt) {
          if (evt.target.id === "info") {
            return;
          }
          var tool = evt.target.id.toLowerCase();
          map.disableMapNavigation();
          tb.activate(tool);
        });
      }

      function addGraphic(evt) {
        console.info(evt);
        //deactivate the toolbar and clear existing graphics
        tb.deactivate();
        map.enableMapNavigation();
        if (evt.geometry.type === "point") {
          var g = new Graphic(evt.geometry, markerSymbol);
          map.graphics.add(g);
          var shape = g.getShape();
          var sp1 = map.toScreen(evt.geometry);
          var mp1 = map.toMap(new ScreenPoint(sp1.x + 50, sp1.y));
          fx.animateTransform({
            duration: 1200,
            shape: shape,
            transform: [{
              name: "translate",
              start: [0,0],
              end: [50, 0]
            }, {
              name: "original"
            }],
            onEnd: lang.hitch(this, function(){
              g.setGeometry(mp1);
            })
          }).play();
        }
      }

    });
  </script>
</head>

<body>
  <div id="info">
    <div>Select and draw on map to add graphic</div>
    <button id="Point">Point</button>
  </div>
  <div id="mapDiv"></div>
</body>
</html>
KrishV
by
Occasional Contributor III

Hello Robert,

Thanks for your response.

I tried code suggested by you to move point from one coordinate to another as shown below. But animate is not shown on map. Please let me know where I'm doing wrong.

<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
    <title></title>
    <link rel="stylesheet" href="https://js.arcgis.com/3.20/esri/css/esri.css">
    <style>
      html, body, #map {
        height: 100%; width: 100%; margin: 0; padding: 0; 
      }
    </style>

    <script src="https://js.arcgis.com/3.20/"></script>
    <script>
      var map;
    
      require(["esri/map","esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
"esri/symbols/PictureFillSymbol", "esri/symbols/CartographicLineSymbol",
      "esri/graphic", "dojox/gfx/fx", "dojo/_base/lang",
      "esri/Color", "dojo/dom", "dojo/on", "esri/geometry/ScreenPoint",
       "dojo/domReady!"],
        function(Map, SimpleMarkerSymbol, SimpleLineSymbol,PictureFillSymbol, CartographicLineSymbol,
      Graphic, fx, lang,
      Color, dom, on, ScreenPoint) 
          {
          var options = { basemap : "gray",  
          center : [-29.88,  21.86133],  
          zoom : 3 };        
         
          map = new esri.Map("mapDiv", options);    
               var linepath = [
[ -29.88231249999835 , 21.861337104185896 ] ,
[ -29.706531249998385 , 23.64436466438422 ] ,
[ -26.89403124999913 , 29.152009189365007 ] ,
[ -25.4877812499995 , 31.57838706044446 ] ,
[ -22.85106250000021 , 34.08891708698886 ] ,
[ -19.862781250001014 , 36.66827922896022 ] ,
[ -18.104968750001476 , 37.787943753057206 ] ,
[ -14.765125000002355 , 39.300164419151855 ] ,
[ -12.655750000002914 , 39.97698664383719 ] ,
[ -10.370593750003529 , 40.64717142579546 ] ,
[ -8.085437500004144 , 41.178522893330914 ] ,
[ -4.218250000005169 , 41.574231022027256 ] ,
[ 0.7036249999935258 , 41.836698107532534 ] ,
[ 4.746593749992446 , 41.836698107532534 ] ,
[ 9.316906249991233 , 41.836698107532534 ] ,
[ 12.48096874999041 , 41.836698107532534 ] ,
[ 12.8325312499903 , 41.836698107532534 ] ,
];

           

var markerSymbol = new SimpleMarkerSymbol();
      markerSymbol.setPath(
        "M16,4.938c-7.732,0-14,4.701-14,10.5c0,1.981,0.741,3.833,2.016,5.414L2,25.272l5.613-1.44c2.339,1.316,5.237,2.106,8.387,2.106c7.732,0,14-4.701,14-10.5S23.732,4.938,16,4.938zM16.868,21.375h-1.969v-1.889h1.969V21.375zM16.772,18.094h-1.777l-0.176-8.083h2.113L16.772,18.094z"
      );
      markerSymbol.setColor(new Color("#00FFFF"));


var gLayerVehicle = new esri.layers.GraphicsLayer({"id" : "Vehicle"});  

 map.addLayer(gLayerVehicle); 
setInterval(test, 3000);
var counter = 0;

function test(){
           
           gLayerVehicle.clear();
            var p1 = new esri.geometry.Point(linepath[counter]);
          var p2 = new esri.geometry.Point(linepath[counter+1]);   
     
          
          var pt1Graphic = new esri.Graphic(p1, markerSymbol);    
          
          gLayerVehicle.add(pt1Graphic);
            
            
            var shape = pt1Graphic.getShape();
          var sp1 = map.toScreen(p1);
            var sp2 = map.toScreen(p2);
            
          var mp1 = map.toMap(new ScreenPoint(sp2.x, sp2.y));
                        
          fx.animateTransform({
                                  duration: 1200,
                                  shape: shape,
                                  transform: [{
  name: "translate",
  start: [sp1.x, (sp1.y - shape.bbox.b)],
  end: [sp2.x, (sp2.y - shape.bbox.b)]
},
{
              name: "original"
            }],
            onEnd: lang.hitch(this, function(){
              pt1Graphic.setGeometry(mp1);
            })

                                          }).play();
             

            counter++;
            }
        }
      );
    </script>
  </head>
  <body>
    <div id="mapDiv"></div>
  </body>
</html>

Regards,

Krish

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

Krish,

   The issue you are having now is that you are setting the animation start and end values the way you were before and I added the "original" property to the animation which mean use the shapes original coords and add the end values to the start original (0,0).

<!DOCTYPE html>
<html>

<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=7,IE=9">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
  <title></title>
  <link rel="stylesheet" href="https://js.arcgis.com/3.20/esri/css/esri.css">
  <style>
    html,
    body,
    #mapDiv {
      height: 100%;
      width: 100%;
      margin: 0;
      padding: 0;
    }
  </style>

  <script src="https://js.arcgis.com/3.20/"></script>
  <script>
    var map;
    require(["esri/map", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
        "esri/graphic", "dojox/gfx/fx", "dojo/_base/lang", "esri/Color", "dojo/dom", "esri/layers/GraphicsLayer",
        "dojo/on", "esri/geometry/ScreenPoint", "esri/geometry/Point", "esri/geometry/Polyline",
        "dojo/domReady!"
      ],
      function(Map, SimpleMarkerSymbol, SimpleLineSymbol,
        Graphic, fx, lang, Color, dom, GraphicsLayer,
        on, ScreenPoint, Point, Polyline) {
        var options = {
          basemap: "gray",
          center: [-29.88, 21.86133],
          zoom: 3
        };

        map = new Map("mapDiv", options);

        var linepath = [
          [-29.88231249999835, 21.861337104185896],
          [-29.706531249998385, 23.64436466438422],
          [-26.89403124999913, 29.152009189365007],
          [-25.4877812499995, 31.57838706044446],
          [-22.85106250000021, 34.08891708698886],
          [-19.862781250001014, 36.66827922896022],
          [-18.104968750001476, 37.787943753057206],
          [-14.765125000002355, 39.300164419151855],
          [-12.655750000002914, 39.97698664383719],
          [-10.370593750003529, 40.64717142579546],
          [-8.085437500004144, 41.178522893330914],
          [-4.218250000005169, 41.574231022027256],
          [0.7036249999935258, 41.836698107532534],
          [4.746593749992446, 41.836698107532534],
          [9.316906249991233, 41.836698107532534],
          [12.48096874999041, 41.836698107532534],
          [12.8325312499903, 41.836698107532534],
        ];

        var sls = new SimpleLineSymbol(
          SimpleLineSymbol.STYLE_DASH,
          new Color([255, 0, 0]),
          3
        );
        var pl = new Polyline({"paths": [linepath], "spatialReference":{"wkid":4326}});
        var vechPath = new Graphic(pl, sls);

        var markerSymbol = new SimpleMarkerSymbol();
        markerSymbol.setPath(
          "M16,4.938c-7.732,0-14,4.701-14,10.5c0,1.981,0.741,3.833,2.016,5.414L2,25.272l5.613-1.44c2.339,1.316,5.237,2.106,8.387,2.106c7.732,0,14-4.701,14-10.5S23.732,4.938,16,4.938zM16.868,21.375h-1.969v-1.889h1.969V21.375zM16.772,18.094h-1.777l-0.176-8.083h2.113L16.772,18.094z"
        );
        markerSymbol.setColor(new Color("#00FFFF"));

        var gLayerVehicle = new GraphicsLayer({
          "id": "Vehicle"
        });
        var gLayerVehiclePath = new GraphicsLayer({
          "id": "VehiclePath"
        });

        map.addLayers([gLayerVehiclePath, gLayerVehicle]);
        gLayerVehiclePath.add(vechPath);

        var myInterval = setInterval(test, 3000);
        var counter = 0;

        function test() {
          gLayerVehicle.clear();
          var p1 = new Point(linepath[counter]);
          var p2 = new Point(linepath[counter + 1]);
          var pt1Graphic = new Graphic(p1, markerSymbol);

          gLayerVehicle.add(pt1Graphic);

          var shape = pt1Graphic.getShape();
          console.info(shape.getTransform());
          var sp1 = map.toScreen(p1);
          var sp2 = map.toScreen(p2);

          var mp1 = map.toMap(new ScreenPoint(sp2.x, sp2.y));

          fx.animateTransform({
            duration: 1200,
            shape: shape,
            transform: [{
                name: "translate",
                start: [0,0],
                end: [sp2.x - sp1.x, sp2.y - sp1.y]
              },
              {name: "original"}
            ],
            onEnd: lang.hitch(this, function() {
              pt1Graphic.setGeometry(mp1);
            })
          }).play();
          counter++;
          if (counter >= linepath.length - 1) {
            clearInterval(myInterval);
          }
        }
      }
    );
  </script>
</head>

<body>
  <div id="mapDiv"></div>
</body>

</html>
KrishV
by
Occasional Contributor III

Hi Robert,

Wow! Perfect!

Thank you so much...!!!

Regards,

Krish

0 Kudos
RobertScheitlin__GISP
MVP Emeritus

There is no other way in 4.x currently. The ability to animate will be improved in future releases.

CyberSmarTalk
New Contributor

Is there any update on this one?

0 Kudos