Select to view content in your preferred language

Search and Zoom in to a location

1631
5
03-09-2022 05:48 AM
Tarak-Kar
New Contributor III

I am plotting some text graphics on a graphics layer and now I need to give an option on the map to search for a specific text and navigate to that location and zoom in. 

Can someone please guide me with the approach? 

Here is the sample code where if I search for 560001, the map should be zoom in to that location.

 

<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
  <style>
    html,
    body,
    #viewDiv {
      padding0;
      margin0;
      height100%;
      width100%;
    }
  </style>
  <link rel="stylesheet" href="https://js.arcgis.com/4.22/esri/themes/light/main.css">
  <script src="https://js.arcgis.com/4.22/"></script>
  <script>
    require([
      "esri/WebMap",
      "esri/views/MapView",
      "esri/Graphic",
      "esri/layers/GraphicsLayer",
      "esri/symbols/TextSymbol"
    ], function (WebMapMapViewGraphicGraphicsLayerTextSymbol) {
      const webmap = new WebMap({
        portalItem: {
          id: "36f72c8a71b542399ca09e10c5aa55f4"
        }
      });
      const view = new MapView({
        container: "viewDiv",
        map: webmap,
        center: [-37.731338217717074175.22263172713014],
        zoom: 10
      });
      this.objectTypeList = [
        { Location: '560001'latitude: -37.731338217717074longitude: 175.22263172713014 },
        { Location: '560002'latitude: -37.487705856583744longitude: 175.09324140306873 },
        { Location: '560003'latitude: -37.505917118655056longitude: 175.12036900524583 },
        { Location: '560005'latitude: -37.67287982024181longitude: 175.23882277753953 },
        { Location: '560005'latitude: -37.67310492511848longitude: 175.23890380457217 }
      ];
      var graphicsLayer = new GraphicsLayer();
      webmap.layers.add(graphicsLayer);
      this.objectTypeList.forEach(item => {
        var point = {
          type: "point",
          longitude: item.longitude,
          latitude: item.latitude
        };
        var textSymbol = new TextSymbol({
          color: "#BB0000",
          haloColor: "black",
          haloSize: "1px",
          text: `${item.Location}`,
          font: { size: 12family: "Josefin Slab"weight: "bold" }
        });
        var pointGraphic = new Graphic({
          geometry: point,
          symbol: textSymbol
        });
        graphicsLayer.add(pointGraphic);
      });
    });
  </script>
</head>
<body>
  <div id="viewDiv"></div>
</body>
</html>
0 Kudos
5 Replies
BlakeTerhune
MVP Regular Contributor

Have you tried the Search Widget?

0 Kudos
Tarak-Kar
New Contributor III

Hi Blake

Can I use Search Widget with GraphicsLayer? Can you please give me some hints on how it should be done in the code in my case?

Also is it possible to navigate to a location based on the lat, long, and zoom in? I have tried view.navTo() but that didn't work.

Thanks.

0 Kudos
BlakeTerhune
MVP Regular Contributor

If you want to zoom to a feature by attribute (560001), the Search widget or Query() method should both work on a graphics layer. The source for the Search widget will be a LayerSearchSource, which notes that "Feature layers created from client-side graphics are not supported." If using Query, you'll also need to use goTo() to zoom the map. The goTo() method will also accept lat, long coordinates to zoom in.

0 Kudos
Tarak-Kar
New Contributor III

Can you please suggest why zoom is working but not the center when I try view.goTo?

view.goTo({
center: [175.22263172713014, -37.731338217717074],
zoom: 15
});

 

0 Kudos
RichardSon
New Contributor

You just need to find the selected (somehow) location in the graphics of GraphicLayer using the symbol text property.Link

Now, you are using geographic (lon, lat) to create the geometries but your map is in another spatial reference system. In that order to zoom to the geometries you will have to project them.

Take a look a the example I put for you, I use a simple select to choose the graphic, and I use a on client projection method, another option would be server side projection.

 

<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
    <style>
        html,
        body,
        #viewDiv {
            padding: 0;
            margin: 0;
            height: 100%;
            width: 100%;
        }
    </style>
    <link rel="stylesheet" href="https://js.arcgis.com/4.22/esri/themes/light/main.css">
    <script src="https://js.arcgis.com/4.22/"></script>
    <script>
        require([
            "esri/WebMap",
            "esri/views/MapView",
            "esri/Graphic",
            "esri/layers/GraphicsLayer",
            "esri/symbols/TextSymbol",
            "esri/geometry/SpatialReference",
            "esri/geometry/projection"
        ], function (WebMap, MapView, Graphic, GraphicsLayer, TextSymbol, SpatialReference, projection) {
            const webmap = new WebMap({
                portalItem: {
                    id: "36f72c8a71b542399ca09e10c5aa55f4"
                }
            });
            const view = new MapView({
                container: "viewDiv",
                map: webmap,
                center: [-37.731338217717074, 175.22263172713014],
                zoom: 10
            });
            this.objectTypeList = [
                { Location: '560001', latitude: -37.731338217717074, longitude: 175.22263172713014 },
                { Location: '560002', latitude: -37.487705856583744, longitude: 175.09324140306873 },
                { Location: '560003', latitude: -37.505917118655056, longitude: 175.12036900524583 },
                { Location: '560004', latitude: -37.67287982024181, longitude: 175.23882277753953 },
                { Location: '560005', latitude: -37.67310492511848, longitude: 175.23890380457217 }
            ];
            var graphicsLayer = new GraphicsLayer();
            webmap.layers.add(graphicsLayer);
            this.objectTypeList.forEach(item => {
                var point = {
                    type: "point",
                    longitude: item.longitude,
                    latitude: item.latitude
                };
                var textSymbol = new TextSymbol({
                    color: "#BB0000",
                    haloColor: "black",
                    haloSize: "1px",
                    text: `${item.Location}`,
                    font: { size: 12, family: "Josefin Slab", weight: "bold" }
                });
                var pointGraphic = new Graphic({
                    geometry: point,
                    symbol: textSymbol
                });
                graphicsLayer.add(pointGraphic);
            });

            projection.load().then(function() {
                const outSR = new SpatialReference({wkid: 2193});
                const dic = {};
                graphicsLayer.graphics.forEach(g => dic[g.symbol.text] = projection.project(g.geometry, outSR));
                view.when(function(){
                    const locationZoomButton = document.getElementById("locationZoomButton");
                    locationZoomButton.addEventListener("click", function(){
                        const locationSelect = document.getElementById("locationSelect");
                        const locationText = locationSelect.value;
                        if (dic.hasOwnProperty(locationText)) {
                            view.goTo(dic[locationText]);
                        }
                    });
                });
            });
        });
    </script>
</head>

<body>
    <div>
        <select id="locationSelect">
            <option value="560001">560001</option>
            <option value="560002">560002</option>
            <option value="560003">560003</option>
            <option value="560004">560004</option>
            <option value="560005">560005</option>
        </select>
        <button id="locationZoomButton"> Zoom </button>
    </div>
    <div id="viewDiv"></div>
</body>

</html>

 

 

0 Kudos