Creating multiple graphics

962
7
Jump to solution
04-26-2023 11:20 AM
TheGamer
Occasional Contributor

So, I'm only able to create one graphic at a time. I was wondering if there is a way to allow the user to add multiple graphics on the map. I basically want the user to be able to add multiple graphics throughout the map using one point-button. Also, if the user decides to change the value for the buffer via slider, this should be applied to all the graphics

 

 

 

 

<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />

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

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

    .ext-box {
      display: table;
      width: 350px;
      height: 100%;
    }

    .int-box {
      display: table-cell;
      vertical-align: top;
      width: 340px;
      height: 260px;
    }

    .FixedHeightContainer {
      float: left;
      height: 380px;
      width: 230px;
      padding: 3px;
      background: rgb(112, 128, 144, 0.5);
    }

    .header {
      height: 30px;
      padding-top: 5px;
    }

    .geometryResultsdiv {
      height: 345px;
      overflow: auto;
      background: #fff;
      font-size: 8px;
    }

    .menu {
      display: table;
      width: 65%;
      border: 1px solid black;
      border-right: none;
      box-sizing: border-box;
    }

    .menu>div {
      display: table-row;
      background-color: white;
    }

    .menu>div>div {
      border-right: 1px solid black;
      display: table-cell;
      text-align: center;
      vertical-align: middle;
    }

    @media screen and (max-width: 240px) {
      .menu {
        display: block;
        float: left;
        width: auto;
        border: none;
      }

      .menu>div {
        display: block;
      }

      .menu>div>div {
        border: none;
        padding-right: 10px;
        display: block;
        text-align: left;
      }
    }

    .boxpadding {
      padding: 0px 0px 5px 8px;
    }

    .float-container {
      border: 3px solid #fff;
      padding: 2px;
    }

    .float-child1 {
      width: 40%;
      float: left;
      padding: 2px;
    }

    .float-child2 {
      width: 25%;
      float: left;
      padding: 2px;
    }
  </style>

  <script>
    require([
      "esri/Map", "esri/views/MapView", "esri/views/draw/Draw", "esri/Graphic", "esri/geometry/geometryEngine",
      "esri/geometry/support/webMercatorUtils",
      "esri/layers/GraphicsLayer",
      "dojo/dom",
      "dojo/domReady!"
    ], (Map, MapView, Draw, Graphic, geometryEngine, webMercatorUtils, GraphicsLayer, dom) => {

      let blayer = new GraphicsLayer({
        id: "layer",
      });
      blayer.opacity = 0.5;
      const map = new Map({
        basemap: "gray-vector",
        layers: [blayer]
      });
      const view = new MapView({
        container: "viewDiv",
        map: map,
        zoom: 10,
        center: [-77.367, 37.55]
      });
      const draw = new Draw({
        view: view
      });
      document.getElementById("clear-button").onclick = () => {
        view.graphics.removeAll();
        blayer.removeAll();
      };
      document.getElementById("point-button").onclick = () => {
        const action = draw.create("point");
        view.focus();
        action.on("cursor-update", function(evt) {
          GraphicPoint(evt.coordinates);
        });
        action.on("draw-complete", function(evt) {
          GraphicPoint(evt.coordinates);
        });
      };

      function GraphicPoint(coordinates) {
        view.graphics.removeAll();
        let point = {
          type: "point", // autocasts as /Point
          x: coordinates[0],
          y: coordinates[1],
          spatialReference: view.spatialReference
        };
        const graphic = new Graphic({
          geometry: point,
          symbol: {
            type: "simple-marker",
            style: "circle",
            color: [0, 0, 0, 0.5],
            size: "9px",
          },
        });
        view.graphics.add(graphic);
        BufferGeom(graphic.geometry);
      }

      function BufferGeom(geom) {
              var d = document.getElementById("distance");
              const buffGeom = geometryEngine.geodesicBuffer(
                  geom,
                  d.value,
                  "kilometers"
                );            
                const buffgra = new Graphic({
                  geometry: buffGeom,
                  symbol: {
                    type: "simple-fill",
                    color: [112, 128, 144, 0],
                  },
                })
                blayer.removeAll();
                blayer.add(buffgra);
              d.addEventListener('change', function (){
                const buffGeom = geometryEngine.geodesicBuffer(
                  geom,
                  d.value,
                  "kilometers"
                );            
                const buffgra = new Graphic({
                  geometry: buffGeom,
                  symbol: {
                    type: "simple-fill",
                    color: [112, 128, 144, 0],
                  },
                })
                blayer.removeAll();
                blayer.add(buffgra);
              })
              
            }
      view.ui.add('point-button', 'top-right')
      view.ui.add('clear-button', 'top-right')

    });
  </script>
</head>

<body>
  <div id="viewDiv">

    <div class="ext-box">
      <div class="int-box">
        <h2 class="boxpadding">Buffer</h2>
        <div class="float-container">
          <div class="float-child2">
            <div class="slider">
                    <label for="fader"> Distance</label>
                    <input
                      id="distance"
                      type="range"
                      value="3"
                      min="1"
                      max="10"
                      step="0.5"
                      oninput="this.nextElementSibling.value = this.value+'km'"
                    />
                    <output>3km</output>
                  </div>
          </div>
        </div>
        </br>
        </br></br>
          <div>
            <div id="clear-button" class="esri-widget esri-widget--button esri-interactive" title="Clear Grpahics">
              <span class="esri-icon-erase"></span>
            </div>
            <div id="point-button" class="esri-widget esri-widget--button esri-interactive" title="Draw point">
              <span class="esri-icon-map-pin"></span>
            </div>
          </div>
        </br>
      </div> <!-- End of int box -->
    </div> <!-- End of ent box -->

  </div>
</body>

</html>

 

 

 

 

@Sage_Wall @UndralBatsukh @Gurunara @GreteSoosalu 

 

 

0 Kudos
1 Solution

Accepted Solutions
UndralBatsukh
Esri Regular Contributor

The problem is you are removing all graphics from your graphicslayer whenever user either creates a point or changes the distance. You need to check that logic. In any case hope you can use one of the following codepens 

Something like this? https://codepen.io/U_B_U/pen/rNqwYQW?editors=1000

Or something like this? https://codepen.io/U_B_U/pen/MWPoOLe?editors=1000

Or like this? https://codepen.io/U_B_U/pen/MWPoOMj?editors=1000

 

View solution in original post

7 Replies
UndralBatsukh
Esri Regular Contributor

Yes! You can use GraphicsLayer.addMany method to add array of graphics.

0 Kudos
TheGamer
Occasional Contributor

Hi @UndralBatsukh , so how do I create an array of graphics? And after that, I would just do blayer.addMany(array)?

 

0 Kudos
UndralBatsukh
Esri Regular Contributor

Yep. 

const graphics = [graphic1, graphic2, graphic3];
bLayer.addMany(graphics);
//or 
bLayer.addMany([graphic1, graphic2, graphic3]);

 

0 Kudos
TheGamer
Occasional Contributor

Hi @UndralBatsukh , I tried doing that but im still only able to produce one graph at a time. Please see the code here: https://codepen.io/Charanb98/pen/wvYdQYV?editors=1000 

0 Kudos
UndralBatsukh
Esri Regular Contributor

What is it you are trying to do? Looks like you are adding point and polygon graphics using GraphicsLayer.addMany. If you can tell me what you are expecting in your codepen then that would help.

0 Kudos
TheGamer
Occasional Contributor

Hi, So I am currently able to add a ring around a point using the buffer method and change the ring size using addEventListener(). But, I can't find a way to display more than 1 ring basically I want the user to be able to add as many rings as they want to by using the point-button

0 Kudos
UndralBatsukh
Esri Regular Contributor

The problem is you are removing all graphics from your graphicslayer whenever user either creates a point or changes the distance. You need to check that logic. In any case hope you can use one of the following codepens 

Something like this? https://codepen.io/U_B_U/pen/rNqwYQW?editors=1000

Or something like this? https://codepen.io/U_B_U/pen/MWPoOLe?editors=1000

Or like this? https://codepen.io/U_B_U/pen/MWPoOMj?editors=1000