graphicsExtent and the single point

6349
8
09-30-2013 12:15 PM
BenFousek
Occasional Contributor III
JS API Team,
Calling graphicsExtent with a single point returns null. I get why this happens, i.e. a single point doesn't have an extent (height and width = 0). When iterating through graphics and zooming to one graphic I can understand filtering in code. For example:

zoomTo: function (gId) {
  array.forEach(this.map.resultsLayer.graphics, function (graphic) {
    if (graphic.gId === gId) {
      if (graphic.geometry.type === 'point') {
        this.map.centerAndZoom(graphic.geometry, 18);
      } else {
        this.map.setExtent(graphic.geometry.getExtent(), true);
      }
      return;
    }
  });
}


I don't mind checking for a single point myself and handling it, but it seems to me graphicsExtent should catch a single point in the graphics array and return a valid extent. Perhaps with a second parameter that when set to true returns a computed extent for a single point. I'm not sure what that would look like from the api's point of view, but something that comes to mind is returning an extent based on map size at the largest level of detail with the point as the center.

Just a suggestion and as always keep up the good work.
0 Kudos
8 Replies
JonathanUihlein
Esri Regular Contributor
Ran into this exact issue when writing an application a while back.

Per suggestion, this is a function I used (I did not write this).

function calcGraphicsExtent(graphicsArray)
{
 var g = graphicsArray[0].geometry,
 fullExt = g.getExtent(),
 ext, i, il = graphicsArray.length;

 if (fullExt === null) {
  fullExt = new Extent(g.x, g.y, g.x, g.y, g.spatialReference);
 }
 for (i=1; i<il; i++) {
  ext = (g = graphicsArray.geometry).getExtent();
  if (ext === null) {
   ext = new Extent(g.x, g.y, g.x, g.y, g.spatialReference);
  }
  fullExt = fullExt.union(ext);
 }
 return fullExt;
}   




Not that you needed help; just wanted to share my solution as it is relevant to this discussion.
0 Kudos
DaveTaylor
New Contributor
I came across this thread when I was trying to do the same thing...I tried using what you have here but I can't get it to work. Below is my code that works for multiple graphic points. How do I incorporate what you have here into my code below?

Thanks in advance!

function showResults(featureSet) {
    //remove all graphics on the maps graphics layer
    map.graphics.clear();
 var extent = esri.graphicsExtent(featureSet.features); 
 map.setExtent(extent.expand(1), true);
    //Performance enhancer - assign featureSet array to a single variable.
    var resultFeatures = featureSet.features;
  
  var railLocationTemplate = new InfoTemplate("Shop Location", 
        "<b>Shop Name: </b>${NAME}<br/>");
         
    for (var i=0, il=resultFeatures.length; i<il; i++) {
      //Get the current feature from the featureSet.
      //Feature is a graphic
      var graphic = resultFeatures;
     // graphic.setSymbol(symbol);

      //Set the infoTemplate.
      graphic.setInfoTemplate(railLocationTemplate);
   console.log("BUTTON CLICKED");
   
      //Add graphic to the map graphics layer.
      map.graphics.add(graphic);
    }
  }
0 Kudos
JonathanUihlein
Esri Regular Contributor
function showResults(featureSet) 
{
  
  map.graphics.clear();
  
  var graphicsArray = [];
  var resultFeatures = featureSet.features;
  var railLocationTemplate = new InfoTemplate("Shop Location", "<b>Shop Name: </b>${NAME}<br/>");
  
  for (var i=0, il=resultFeatures.length; i<il; i++) {
    var graphic = resultFeatures;
    graphic.setInfoTemplate(railLocationTemplate);
    graphicsArray.push(graphic);
  }
  
  var extent = calcGraphicsExtent(graphicsArray);
  
  map.setExtent(extent, true).then(function(){            
    for(var i=0; i<graphicsArray.length; i++) {
      map.graphics.add(graphicsArray);
    }
  });
  
}


function calcGraphicsExtent(graphicsArray)
{
    var g = graphicsArray[0].geometry,
    fullExt = g.getExtent(),
    ext, i, il = graphicsArray.length;

    if (fullExt === null) {
        fullExt = new Extent(g.x, g.y, g.x, g.y, g.spatialReference);
    }
    for (i=1; i<il; i++) {
        ext = (g = graphicsArray.geometry).getExtent();
        if (ext === null) {
            ext = new Extent(g.x, g.y, g.x, g.y, g.spatialReference);
        }
        fullExt = fullExt.union(ext);
    }
    return fullExt;
}


Something like this will probably work.
0 Kudos
ReneRubalcava
Frequent Contributor
This can work too
if (graphic.geometry.type === 'point') {
  var maxZoom = map.getMaxZoom();
  map.centerAndZoom(graphic.geometry, maxZoom - 1);
} else {
  map.setExtent(graphicsUtils.graphicsExtent([graphic]));
}
0 Kudos
BenFousek
Occasional Contributor III
Rene...yep. I use
if (this.graphics.length === 1 && this.graphics[0].geometry.type === 'point')
for a generic check. I actually ran into an issue with a dataset in which the queries being made by the user regularly return multiple records at the same point. graphicsExtent also returns null in this situation but not as easy to check. I think they are considering graphicsExtent returning an extent with the point(s) at the center in these situations.
0 Kudos
DaveTaylor
New Contributor
I am getting the following in chrome:

ReferenceError: Extent is not defined

Do I need to require anything at the top?

require(["dojo/ready",
      "dojo/on", "esri/map",
      "esri/InfoTemplate", 
      "esri/layers/ArcGISDynamicMapServiceLayer", 
      "esri/symbols/SimpleFillSymbol", 
      "esri/symbols/SimpleLineSymbol", 
      "esri/tasks/IdentifyTask", 
      "esri/tasks/IdentifyParameters", 
      "esri/dijit/Popup", 
      "dojo/_base/array", 
      "esri/Color", 
      "dojo/dom-construct",
      "esri/tasks/QueryTask",
      "esri/tasks/query", "esri/urlUtils", 
"esri/dijit/BasemapToggle", "esri/symbols/SimpleMarkerSymbol", "dojo/domReady!",  "esri/Credential",
                      "esri/config"
], 
      function(ready, on, Map, InfoTemplate, ArcGISDynamicMapServiceLayer, SimpleFillSymbol, SimpleLineSymbol, IdentifyTask, IdentifyParameters, 
      Popup, arrayUtils, Color, domConstruct, QueryTask, Query, urlUtils, BasemapToggle, SimpleMarkerSymbol) 
0 Kudos
DaveTaylor
New Contributor
Got it thanks all!

I did forget this:

"esri/geometry/Extent"
0 Kudos
BenFousek
Occasional Contributor III
0 Kudos