Using a Local .png File For a PictureMarkerSymbol

3413
10
Jump to solution
05-11-2019 12:10 PM
MichaelCollins6
New Contributor II

Hi All:

I am making a map and would like to use a picturemarkersymbol with a local png to symbolize a mapimagelayer's sublayer. I have tried what is in the documentation to the tune of:

renderer: {
   type: "simple",
   symbol: {
      type: "picture-marker",
      url: 'img/busStop.png',
      width: 22,
      height: 22
   }
}

Now, if I put a png from another source in there (say from a google image search), it will show up on the map fine. This way, not so much. Could somebody lead me in the right direction?

Thanks!

0 Kudos
1 Solution

Accepted Solutions
RobertScheitlin__GISP
MVP Esteemed Contributor

Michael,

   OK I have verified that there seems to be a bug where locally hosted images do not work. This is something you will have to report to esri tech support. Here is a sample that demos the issue. The Picturemarker symbol works if you have a directory called images and a image named search-pointer.png as it will work when adding it to the view as a graphic but will not work if used as a sublayers renderer symbol:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  <title>MapImageLayer - Toggle sublayer visibility - 4.11</title>

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

  <script>
    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/layers/MapImageLayer",
      "esri/symbols/PictureMarkerSymbol",
      "esri/Graphic"
    ], function (Map, MapView, MapImageLayer, PictureMarkerSymbol, Graphic) {
      /*****************************************************************
       * Create a renderer for the dynamic data layer (table).
       *****************************************************************/

      var renderer = {
        type: "simple", // autocasts as new SimpleRenderer()
        symbol: {
          type: "simple-line", // autocasts as new SimpleLineSymbol()
          color: [255, 255, 255, 0.5],
          width: 0.75,
          style: "long-dash-dot-dot"
        }
      };

      var pms = new PictureMarkerSymbol({
        url: 'images/search-pointer.png', //this does not for a sublayer symbol
        //url: 'https://js.arcgis.com/3.28/esri/dijit/Search/images/search-pointer.png', //this works
        width: "22px",
        height: "22px"
      });

      /*****************************************************************
       * Create a MapImageLayer instance pointing to a Map Service
       * containing data about US Cities, Counties, States and Highways.
       * Define sublayers with visibility for each layer in Map Service.
       *****************************************************************/
      var layer = new MapImageLayer({
        url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer",
        sublayers: [{
            id: 2,
            visible: true
          },
          {
            id: 4,
            visible: false,
            title: "Railroads",
            renderer: renderer,
            source: {
              // indicates the source of the sublayer is a dynamic data layer
              type: "data-layer",
              // this object defines the data source of the layer
              // in this case it's a feature class table from a file geodatabase
              dataSource: {
                type: "table",
                // workspace name
                workspaceId: "MyDatabaseWorkspaceIDSSR2",
                // table name
                dataSourceName: "ss6.gdb.Railroads"
              }
            }
          },
          {
            id: 1,
            visible: true
          },
          {
            id: 0,
            renderer: {
              type: 'simple',
              symbol: pms
            },
            visible: true
          }
        ]
      });

      /*****************************************************************
       * Add the layer to a map
       *****************************************************************/
      var map = new Map({
        basemap: "dark-gray",
        layers: [layer]
      });

      var view = new MapView({
        container: "viewDiv",
        map: map,
        zoom: 4,
        center: [-99, 39]
      });

      view.when( function(){
        var gra = new Graphic({
          geometry: view.center,
          symbol: pms
        });
        view.graphics.add(gra);
      });

      /*****************************************************************
       * Wait for Layer to load and update the page to refelect which
       * layers are visible in the Map Service.
       *****************************************************************/
      layer.when(function () {
        layer.sublayers.map(function (sublayer) {
          var id = sublayer.id;
          var visible = sublayer.visible;
          var node = document.querySelector(
            ".sublayers-item[data-id='" + id + "']"
          );
          if (visible) {
            node.classList.add("visible-layer");
          }
        });
      });

      /*****************************************************************
       * Listen for when buttons on the page have been clicked to turn
       * layers on and off in the Map Service.
       *****************************************************************/
      var sublayersElement = document.querySelector(".sublayers");
      sublayersElement.addEventListener("click", function (event) {
        var id = event.target.getAttribute("data-id");
        if (id) {
          var sublayer = layer.findSublayerById(parseInt(id));
          var node = document.querySelector(
            ".sublayers-item[data-id='" + id + "']"
          );
          sublayer.visible = !sublayer.visible;
          node.classList.toggle("visible-layer");
        }
      });
    });
  </script>

  <style>
    html,
    body {
      font-family: sans-serif;
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }

    #viewDiv {
      position: absolute;
      right: 0;
      left: 0;
      top: 0;
      bottom: 60px;
    }

    .footer {
      position: absolute;
      bottom: 0;
      height: 60px;
      width: 100%;
    }

    .sublayers {
      margin: 0 auto;
      display: flex;
      flex-direction: row;
      justify-content: center;
      align-items: center;
      overflow: auto;
    }

    .sublayers-item {
      flex-grow: 4;
      background-color: rgba(34, 111, 14, 0.5);
      color: #fff;
      margin: 1px;
      width: 50%;
      padding: 20px;
      overflow: auto;
      text-align: center;
      cursor: pointer;
      font-size: 0.7em;
    }

    .visible-layer {
      color: #fff;
      background-color: #226f0e;
    }
  </style>
</head>

<body>
  <div id="viewDiv"></div>
  <div class="footer">
    <div class="sublayers">
      <div class="sublayers-item" data-id="0">Cities</div>
      <div class="sublayers-item" data-id="1">Highways</div>
      <div class="sublayers-item" data-id="4">Railroads</div>
      <div class="sublayers-item" data-id="2">States</div>
    </div>
  </div>
</body>

</html>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

0 Kudos
10 Replies
RobertScheitlin__GISP
MVP Esteemed Contributor

Michael,

   So in your app in the folder where you have your .html file you have a img folder that has a busStop.png file and that file is named with the exact same cAsE?

0 Kudos
MichaelCollins6
New Contributor II

Something like that. I have a script that loads the image as follows:

bufferLayers = new MapImageLayer({

// The layers must be in reverse order of how they are displayed in the REST interface otherwise

// it tries to render them dynamically which is not possible in 10.31.

url: bufferLayersURL,

title: "Other Map Features",

visible: true,

sublayers: [

{

id: busStopsPedJoinLayerID,

title: "Pedestrian-Bus Stop Buffers Join",

outFields: ["*"],

visible: false

},

,

,

,

,

label: 'Bus Stop Location'

},

popupTemplate: Bus Stop',

outFields: ["*"],

content: busStopContent

}

},

,

label: 'School Location'

},

popupTemplate: (<1mi)",

outFields: ["*"],

content: schoolContent

}

}

]

});

The weird part is that if I change the bus stop icon to “../img/busStop.png” it works fine, but the schools no longer show up. Neither show up if I load both locally. The only way to make it work is to use the janky web hosted images as above. Do I have to use a fully qualified location? As in publish it to the server then use an address as above?

Best,

Michael Collins

d +1 (646) 791-8814 | c +1 (651) 323-8431

An Equal Opportunity Employer

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Michael,

   I'm confused there is nothing in the code you shared that has anything to do with using a local png file...?

0 Kudos
MichaelCollins6
New Contributor II

Hey Robert:

If I change what I sent to you to what is below, as I mentioned in my previous email (sorry it was unclear), I see no symbols. So…

  • Both png files hosted external => everything is fine

  • Bus stop png file local, school file external => bus stop shows up, but school does not

  • Both files local => nothing shows up

bufferLayers = new MapImageLayer({

// The layers must be in reverse order of how they are displayed in the REST interface otherwise

// it tries to render them dynamically which is not possible in 10.31.

url: bufferLayersURL,

title: "Other Map Features",

visible: true,

sublayers: [

{

id: busStopsPedJoinLayerID,

title: "Pedestrian-Bus Stop Buffers Join",

outFields: ["*"],

visible: false

},

,

,

,

,

label: 'Bus Stop Location'

},

popupTemplate: Bus Stop',

outFields: ["*"],

content: busStopContent

}

},

,

label: 'School Location'

},

popupTemplate: (<1mi)",

outFields: ["*"],

content: schoolContent

}

}

]

});

Michael Collins, E.I.T.

d +1 (646) 791-8814 | c +1 (651) 323-8431

An Equal Opportunity Employer

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Michael,

   I am still not seeing where in the provided code you are setting the sublayers renderer or your renderer code so that I can verify your code.

0 Kudos
MichaelCollins6
New Contributor II

Strange, the sublayers in question are being stripped out, this should be clearer:

,

label: 'Bus Stop Location'

},

popupTemplate: Bus Stop',

outFields: ["*"],

content: busStopContent

}

},

,

label: 'School Location'

}

Michael Collins, E.I.T.

d +1 (646) 791-8814 | c +1 (651) 323-8431

An Equal Opportunity Employer

0 Kudos
MichaelCollins6
New Contributor II

Not better, probably worse. I have attached a text file with the code. Maybe that will work better.

Michael Collins, E.I.T.

d +1 (646) 791-8814 | c +1 (651) 323-8431

An Equal Opportunity Employer

0 Kudos
RobertScheitlin__GISP
MVP Esteemed Contributor

Michael,

   OK I have verified that there seems to be a bug where locally hosted images do not work. This is something you will have to report to esri tech support. Here is a sample that demos the issue. The Picturemarker symbol works if you have a directory called images and a image named search-pointer.png as it will work when adding it to the view as a graphic but will not work if used as a sublayers renderer symbol:

<!DOCTYPE html>
<html>

<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no" />
  <title>MapImageLayer - Toggle sublayer visibility - 4.11</title>

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

  <script>
    require([
      "esri/Map",
      "esri/views/MapView",
      "esri/layers/MapImageLayer",
      "esri/symbols/PictureMarkerSymbol",
      "esri/Graphic"
    ], function (Map, MapView, MapImageLayer, PictureMarkerSymbol, Graphic) {
      /*****************************************************************
       * Create a renderer for the dynamic data layer (table).
       *****************************************************************/

      var renderer = {
        type: "simple", // autocasts as new SimpleRenderer()
        symbol: {
          type: "simple-line", // autocasts as new SimpleLineSymbol()
          color: [255, 255, 255, 0.5],
          width: 0.75,
          style: "long-dash-dot-dot"
        }
      };

      var pms = new PictureMarkerSymbol({
        url: 'images/search-pointer.png', //this does not for a sublayer symbol
        //url: 'https://js.arcgis.com/3.28/esri/dijit/Search/images/search-pointer.png', //this works
        width: "22px",
        height: "22px"
      });

      /*****************************************************************
       * Create a MapImageLayer instance pointing to a Map Service
       * containing data about US Cities, Counties, States and Highways.
       * Define sublayers with visibility for each layer in Map Service.
       *****************************************************************/
      var layer = new MapImageLayer({
        url: "http://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer",
        sublayers: [{
            id: 2,
            visible: true
          },
          {
            id: 4,
            visible: false,
            title: "Railroads",
            renderer: renderer,
            source: {
              // indicates the source of the sublayer is a dynamic data layer
              type: "data-layer",
              // this object defines the data source of the layer
              // in this case it's a feature class table from a file geodatabase
              dataSource: {
                type: "table",
                // workspace name
                workspaceId: "MyDatabaseWorkspaceIDSSR2",
                // table name
                dataSourceName: "ss6.gdb.Railroads"
              }
            }
          },
          {
            id: 1,
            visible: true
          },
          {
            id: 0,
            renderer: {
              type: 'simple',
              symbol: pms
            },
            visible: true
          }
        ]
      });

      /*****************************************************************
       * Add the layer to a map
       *****************************************************************/
      var map = new Map({
        basemap: "dark-gray",
        layers: [layer]
      });

      var view = new MapView({
        container: "viewDiv",
        map: map,
        zoom: 4,
        center: [-99, 39]
      });

      view.when( function(){
        var gra = new Graphic({
          geometry: view.center,
          symbol: pms
        });
        view.graphics.add(gra);
      });

      /*****************************************************************
       * Wait for Layer to load and update the page to refelect which
       * layers are visible in the Map Service.
       *****************************************************************/
      layer.when(function () {
        layer.sublayers.map(function (sublayer) {
          var id = sublayer.id;
          var visible = sublayer.visible;
          var node = document.querySelector(
            ".sublayers-item[data-id='" + id + "']"
          );
          if (visible) {
            node.classList.add("visible-layer");
          }
        });
      });

      /*****************************************************************
       * Listen for when buttons on the page have been clicked to turn
       * layers on and off in the Map Service.
       *****************************************************************/
      var sublayersElement = document.querySelector(".sublayers");
      sublayersElement.addEventListener("click", function (event) {
        var id = event.target.getAttribute("data-id");
        if (id) {
          var sublayer = layer.findSublayerById(parseInt(id));
          var node = document.querySelector(
            ".sublayers-item[data-id='" + id + "']"
          );
          sublayer.visible = !sublayer.visible;
          node.classList.toggle("visible-layer");
        }
      });
    });
  </script>

  <style>
    html,
    body {
      font-family: sans-serif;
      padding: 0;
      margin: 0;
      height: 100%;
      width: 100%;
    }

    #viewDiv {
      position: absolute;
      right: 0;
      left: 0;
      top: 0;
      bottom: 60px;
    }

    .footer {
      position: absolute;
      bottom: 0;
      height: 60px;
      width: 100%;
    }

    .sublayers {
      margin: 0 auto;
      display: flex;
      flex-direction: row;
      justify-content: center;
      align-items: center;
      overflow: auto;
    }

    .sublayers-item {
      flex-grow: 4;
      background-color: rgba(34, 111, 14, 0.5);
      color: #fff;
      margin: 1px;
      width: 50%;
      padding: 20px;
      overflow: auto;
      text-align: center;
      cursor: pointer;
      font-size: 0.7em;
    }

    .visible-layer {
      color: #fff;
      background-color: #226f0e;
    }
  </style>
</head>

<body>
  <div id="viewDiv"></div>
  <div class="footer">
    <div class="sublayers">
      <div class="sublayers-item" data-id="0">Cities</div>
      <div class="sublayers-item" data-id="1">Highways</div>
      <div class="sublayers-item" data-id="4">Railroads</div>
      <div class="sublayers-item" data-id="2">States</div>
    </div>
  </div>
</body>

</html>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
MichaelCollins6
New Contributor II

Thanks for your help on this Robert!!!

Michael Collins, E.I.T.

d +1 (646) 791-8814 | c +1 (651) 323-8431

An Equal Opportunity Employer

0 Kudos