Select to view content in your preferred language

Zooming to the Wrong Location

144
1
06-11-2024 12:21 AM
TapanPatra1
New Contributor

Hi all,

My have a small issue, but it feels challenging as I am new here. When a cluster image is clicked, it should zoom to the maximum level and display only the points data without the cluster.

The code below handles the click event on each cluster image and zooms to the maximum level, but it zooms to the wrong location. I expect it to zoom to the specific location where all the data inside the clicked cluster image is available.

 please provide guidance on how to handle this scenario?

Thanks

 

 

 

<html lang="en">

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  <title>GeoJSONLayer | Sample | ArcGIS Maps SDK for JavaScript 4.29</title>

  <style>
    html,
    body,
    #viewDiv {
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }

  </style>

  <link rel="stylesheet" href="https://js.arcgis.com/4.29/esri/themes/light/main.css" />
  <script src="https://js.arcgis.com/4.29/"></script>

  <script>
    require(["esri/Map", "esri/layers/GeoJSONLayer", "esri/views/MapView"], (
      Map,
      GeoJSONLayer,
      MapView
    ) => {
      const url = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson";

      
      const template = {
        title: "Earthquake Info",
        content: "Magnitude {mag} {type} hit {place} on {time}",
        fieldInfos: [
          {
            fieldName: 'time',
            format: {
              dateFormat: 'short-date-short-time'
            }
          }
        ]
      };

      const renderer = {
        type: "simple",
        field: "mag",
        symbol: {
          type: "simple-marker",
          color: "orange",
          outline: {
            color: "white"
          }
        },
        visualVariables: [{
          type: "size",
          field: "mag",
          stops: [{
              value: 2.5,
              size: "4px"
            },
            {
              value: 8,
              size: "40px"
            }
          ]
        }]
      };

      const geojsonLayer = new GeoJSONLayer({
        url: url,
        featureReduction: {
            type: "cluster",
            clusterRadius: "150px",
              popupTemplate: {
                title: "Cluster summary",
                content: "This cluster contains {cluster_count} points."
              },
              symbol: {
                type: "picture-marker", 
                url: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQa88gtYlcIGYRv5X5yEs7NbJ5JkJdDvzCmLf41BtSCgHqCodZV2fa4ZIjCjroPj27SQCE&usqp=CAU",
                },
            },
        popupTemplate: template,
        renderer: renderer,
        orderBy: {
          field: "mag"
        }
      });

      const map = new Map({
        basemap: "gray-vector",
        layers: [geojsonLayer]
      });

      const view = new MapView({
        container: "viewDiv",
        center: [-168, 46],
        zoom: 2,
        map: map
      });
      
      //onclick of cluster image
      view.on("click", (event) => {
        view.hitTest(event).then(({ results }) => {
          console.log(results[0])
          if(results[0].graphic.attributes.cluster_count && results[0].graphic.attributes.cluster_count > 1){
            view.goTo(results[0].graphic.geometry).then(() => {
              view.zoom = 23;
            })
          }
        });
      });
    
    });

  </script>
</head>

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

</html>

 

 

 

0 Kudos
1 Reply
JoelBennett
MVP Regular Contributor

The problem here is that you're zooming in as much as possible upon the geometry of the cluster graphic itself.  However, there's no guarantee that any of the points represented by that cluster will be within the extent of the view after zooming in.

Instead, you need to get a reference to the points represented by the cluster, and zoom to the extent of those points.  Therefore, you'll need something more like this:

 

view.on("click", (event) => {
  view.hitTest(event,{include:geojsonLayer}).then(({ results }) => {
    console.log(results[0])
    if(results[0].graphic.attributes.cluster_count && results[0].graphic.attributes.cluster_count > 1){
      //get a reference to the LayerView in order to do a client-side query
      var layerView = view.layerViews.find(function(layerView) { return (layerView.layer == geojsonLayer); });

      //create the query that will return the features associated with the cluster
      var query = layerView.createQuery();
      query.aggregateIds = [results[0].graphic.getObjectId()];

      //get the associated features and zoom to them
      layerView.queryFeatures(query).then(function(featureSet) {
        if (featureSet.features.length !== 0)
          view.goTo(featureSet.features);
      });
    }
  });
});

 

 

What you're trying to achieve may not be an "exact science" though.  Although this will zoom to the minimum bounding rectangle of the points in the original cluster, some of those points may be close enough together that they appear as a new cluster of their own.    Or in other cases, there may be other points still in the view that weren't part of the original cluster as well.

0 Kudos