Using a Local .png File For a PictureMarkerSymbol

2298
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>‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍

View solution in original post

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