setExtent zooms in too far

1400
2
Jump to solution
03-07-2017 11:25 AM
KenGalluccio
New Contributor III

I have some code that will allow a user to geocode two addresses.  It will display the points of the addresses on the map.

I want to then set the extent of the map to the two points.  To accomplish this I get the x and y coordinates of both points, create a polyline, get and set the extent of the polyline as the new extent of the map.

The problem is that the new extent is zoomed in a bit to far and you have to zoom out one level to see the points.

To get around this i thought I would be able to get the zoom level after the setExtent using the extent-change listener and add one to it to zoom the map out one level.

Problem is if I put the setZoom within the extent-change listener function, the code will get into a loop.

If I put the setZoom outside this function it is undefined.

Specifically the lines starting at 252 are in question.

I am not sure what else I can check or where else I can put the setZoom so that it does not get called until zoom is populated.

/**
 * Created by Student on 11/20/2014.
 */
var mapMain;
var fromXCoord;
var toXCoord;
var pLine;
var fPoint;
var tPoint;
var fromZone;
var toZone;
var fZone;
var tZone;
var numPass;

// @formatter:off
require([
        "esri/map",
          "esri/SpatialReference",
          "esri/geometry/webMercatorUtils", 
        "esri/geometry/Extent",
          "esri/InfoTemplate",
        "esri/layers/FeatureLayer",
          "esri/layers/LabelClass",
        "esri/dijit/Scalebar",
          "esri/symbols/SimpleFillSymbol",
          "esri/symbols/SimpleLineSymbol",
          "esri/symbols/SimpleMarkerSymbol",
          "esri/symbols/TextSymbol",
          "esri/Color", 
          "esri/renderers/SimpleRenderer",
          "esri/renderers/UniqueValueRenderer",
          "esri/dijit/Search",
          "esri/graphic",
          "esri/geometry/Polyline",
          "esri/geometry/Point",
          "esri/tasks/query",
          "esri/tasks/QueryTask", 
          
        "dojo/ready",
        "dojo/parser",
        "dojo/on",
          "dojo/domReady!",
          "dojo/promise/all",
          
        "dijit/layout/BorderContainer",
        "dijit/layout/ContentPane",
          "dijit/TitlePane",
          "dijit/registry"
          ],
    function(
        Map,SpatialReference,webMercatorUtils,Extent,InfoTemplate,FeatureLayer,LabelClass,Scalebar,SimpleFillSymbol,SimpleLineSymbol,SimpleMarkerSymbol,TextSymbol,Color,SimpleRenderer,UniqueValueRenderer,
          Search,Graphic,Polyline,Point,Query,QueryTask, 
        ready, parser, on, all,
        BorderContainer, ContentPane, TitlePane, registry

        ) {
// @formatter:on

        // Wait until DOM is ready *and* all outstanding require() calls have been resolved
        ready(function() {
          
            // Parse DOM nodes decorated with the data-dojo-type attribute
            parser.parse();
                                   
                /*
                * Step: Specify the initial extent
                * Note: Exact coordinates may vary slightly from snippet/solution
                */
               var extentInitial = new Extent({
                 "xmin" : -74.0249340000041,
                 "ymin" : 42.5025420000134,
                 "xmax" : -73.5927189999818,
                 "ymax" : 43.1172190002567,
                 "spatialReference" : {
                    "wkid" : 4326
                 }
               });

               // Create the map
            mapMain = new Map("cpCenter", {
                basemap : "osm",
                    extent : extentInitial,
                    showLabels : true
            });
               
            /*
             * Step: Add the taxi layer layer to the map
             */
               var albTaxiLayerURL = "http://services2.arcgis.com/A3lMfLhXIUtyxP6p/arcgis/rest/services/CityOfAlbanyTaxi/FeatureServer/0"
                              
               //Step: Specify the output fields.
               var taxiOutFields = ["OBJECTID", "Zone", "Fare"];

               //Template for popup when user clicks a zone.
               var taxiTemplate = new InfoTemplate();
               taxiTemplate.setTitle("</br><tr><td><b>Zone: ${Zone}</b></tr></td>");
               taxiTemplate.setContent("<tr><b>Fare: $</b><td>${Fare}</td></tr></br>");

               //Construct the taxi layer
               var taxiLyr = new FeatureLayer(albTaxiLayerURL, {
                 infoTemplate : taxiTemplate,
                 outFields : taxiOutFields,
               });
               
               var defStyle = new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
               new SimpleLineSymbol(SimpleLineSymbol.STYLE_NULL,new Color([0,0,0])),new Color([215,252,216,0.75])
               );
               
               //This section crate the thematic to color code each zone
               var renderer = new UniqueValueRenderer(defStyle, "Zone");
                    //add symbol for each possible value
                    renderer.addValue("A", new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                                                new SimpleLineSymbol(SimpleLineSymbol.STYLE_NULL,new Color([0,0,0])),new Color([49,70,140, .25])));
                    renderer.addValue("B", new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                                                new SimpleLineSymbol(SimpleLineSymbol.STYLE_NULL,new Color([0,0,0])),new Color([159,188,245, .25])));
                    renderer.addValue("C", new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                                                new SimpleLineSymbol(SimpleLineSymbol.STYLE_NULL,new Color([0,0,0])),new Color([135,59,92, .25])));
                    renderer.addValue("D", new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                                                new SimpleLineSymbol(SimpleLineSymbol.STYLE_NULL,new Color([0,0,0])),new Color([68,135,108, .25])));
                    renderer.addValue("E", new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                                                new SimpleLineSymbol(SimpleLineSymbol.STYLE_NULL,new Color([0,0,0])),new Color([245,95,235, .25])));
                    renderer.addValue("F", new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                                                new SimpleLineSymbol(SimpleLineSymbol.STYLE_NULL,new Color([0,0,0])),new Color([227,117,84, .25])));
                    renderer.addValue("G", new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                                                new SimpleLineSymbol(SimpleLineSymbol.STYLE_NULL,new Color([0,0,0])),new Color([232,245,115, .25])));
                    renderer.addValue("X", new SimpleFillSymbol(SimpleFillSymbol.STYLE_SOLID,
                                                new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID,new Color([0,0,0]),.5),new Color([232,245,115, 0])));

               taxiLyr.setRenderer(renderer);          
               
               // create a text symbol to define the style of labels
               var labelColor = new Color("#666");
               var zoneLabel = new TextSymbol().setColor(labelColor);
               zoneLabel.font.setSize("14pt");
               zoneLabel.font.setFamily("arial");
               var json = {
                    "labelExpressionInfo": {"value": "{Zone}"}
               };
               //create instance of LabelClass (note: multiple LabelClasses can be passed in as an array)
               var labelClass = new LabelClass(json);
               labelClass.symbol = zoneLabel; // symbol also can be set in LabelClass' json
               taxiLyr.setLabelingInfo([ labelClass ]);

               mapMain.addLayer(taxiLyr);
               mapMain.centerAndZoom(new Point(-73.769879, 42.662037, new SpatialReference({ wkid: 4326 })), 12);
               
            /*
             * Step: Add the scalebar widget to the map
             */
            var scalebar = new Scalebar({
                map: mapMain,
                // "dual" displays both miles and kilmometers
                // "english" is the default, which displays miles
                // use "metric" for kilometers
                scalebarUnit: "dual"
            });

               //from address geocoder
               var fromSearch = new Search({
               enableLabel: true,
               enableInfoWindow: false,
                  autoNavigate: false,
               map: mapMain
            }, "");

               fromSearch.startup();

               //to address geocoder
               var toSearch = new Search({
               enableLabel: true,
               enableInfoWindow: false,
                  autoNavigate: false,
               map: mapMain
            }, "");

               toSearch.startup();
               
               dijit.registry.byId("goButton").on("click", doSearchValue);
               
               function doSearchValue(e) {

                    var fromAddress = document.getElementById("fromAddr").value
                    //alert(fromAddress);
                       //highlight symbol

                         fromGeocodeSymbol = new SimpleMarkerSymbol(
                           SimpleMarkerSymbol.STYLE_CIRCLE, 
                           20, 
                           new SimpleLineSymbol(
                              SimpleLineSymbol.STYLE_SOLID, 
                              new Color([85,82,82, 0.5]), 
                              10
                           ), new Color([76,230,0, 0.9]));

                       fromSearch.sources[0].highlightSymbol = fromGeocodeSymbol; //set the symbol for the highlighted symbol

                       fromSearch.search(fromAddress);

                    var toAddress = document.getElementById("toAddr").value
                    //alert(toAddress);
                       //highlight symbol
                         var toGeocodeSymbol = new SimpleMarkerSymbol(
                           SimpleMarkerSymbol.STYLE_CIRCLE, 
                           20, 
                           new SimpleLineSymbol(
                              SimpleLineSymbol.STYLE_SOLID, 
                              new Color([85,82,82, 0.5]), 
                              10
                           ), new Color([245,29,29, 0.9]));

                       toSearch.sources[0].highlightSymbol = toGeocodeSymbol; //set the symbol for the highlighted symbol

                       //If multiple results are found, it will default and select the first.
                       toSearch.search(toAddress);
                       
                    //get coordinates of toAddress to pass to use to create polyline for zooming to extent.                       
                    fromSearch.on('select-result', function(result){
                         fromWebCoords = webMercatorUtils.webMercatorToGeographic(result.result.feature.geometry); 
                         getCoordsAndZoom(fromWebCoords, "from");
                         });  
                    toSearch.on('select-result', function(result){
                         toWebCoords = webMercatorUtils.webMercatorToGeographic(result.result.feature.geometry);
                         getCoordsAndZoom(toWebCoords, "to");
                         }); 

                         
                    function getCoordsAndZoom(geoResults, which){
                         
                         if(which === "from"){
                              fromXCoord = geoResults.x;
                              fromYCoord = geoResults.y;
                              fPoint = new Point(fromXCoord, fromYCoord, new SpatialReference({ wkid: 4326 }));
                              //console.log("In checkResults from " + fromXCoord);
                                                            
                         }else{
                              toXCoord = geoResults.x;
                              toYCoord = geoResults.y;
                              tPoint = new Point(toXCoord, toYCoord, new SpatialReference({ wkid: 4326 }));

                         }
                         
                         if(fromXCoord && fromYCoord && toXCoord && toYCoord){
                              var zoom;

                              //Create polyline that will be used to zoom to the extent of both points that were geocoded
                              var pLine = new Polyline(new SpatialReference({wkid:4326}));
                              pLine.addPath([[fromXCoord, fromYCoord],[toXCoord, toYCoord]]);

                              mapMain.setExtent(pLine.getExtent());

                              mapMain.on('extent-change', function(){
                                   zoom = mapMain.getZoom() + 1;
                              });
                              
                              if (zoom){
                                   mapMain.setZoom(zoom);     
                              }                              
                         }
                                             
                    };
            }
        });
    });
Tags (3)
0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Emeritus

Ken,

  You should just expand the extent of the polyline before you set the maps extent:

                         if(fromXCoord && fromYCoord && toXCoord && toYCoord){
                              var zoom;

                              //Create polyline that will be used to zoom to the extent of both points that were geocoded
                              var pLine = new Polyline(new SpatialReference({wkid:4326}));
                              pLine.addPath([[fromXCoord, fromYCoord],[toXCoord, toYCoord]]);

                              mapMain.setExtent(pLine.getExtent().expand(1.2), true); // the second parameter ensure that the extent fit into the zoom level
                              //expand(1.2) means take the extent and expand it by 20%

                         //No need for the foloowing lines
                              //mapMain.on('extent-change', function(){
                              //     zoom = mapMain.getZoom() + 1;
                              //});
                              
                              //if (zoom){
                              //     mapMain.setZoom(zoom);     
                              //}                              
                         }

View solution in original post

2 Replies
RobertScheitlin__GISP
MVP Emeritus

Ken,

  You should just expand the extent of the polyline before you set the maps extent:

                         if(fromXCoord && fromYCoord && toXCoord && toYCoord){
                              var zoom;

                              //Create polyline that will be used to zoom to the extent of both points that were geocoded
                              var pLine = new Polyline(new SpatialReference({wkid:4326}));
                              pLine.addPath([[fromXCoord, fromYCoord],[toXCoord, toYCoord]]);

                              mapMain.setExtent(pLine.getExtent().expand(1.2), true); // the second parameter ensure that the extent fit into the zoom level
                              //expand(1.2) means take the extent and expand it by 20%

                         //No need for the foloowing lines
                              //mapMain.on('extent-change', function(){
                              //     zoom = mapMain.getZoom() + 1;
                              //});
                              
                              //if (zoom){
                              //     mapMain.setZoom(zoom);     
                              //}                              
                         }
KenGalluccio
New Contributor III

Thanks, works perfect!

0 Kudos