Custon SVG icon on ArcGIS map widget - arcgis

I have to add a custon SVG file instead of the navigation icon from ArcGIS in the 'locate' widget ('esri-icon-locate'). Here the problem is, the default icon is appearing top of the custom svg file. Is there any way to hide the default icon?
view.when(_ => {
const n = document.getElementsByClassName("esri-icon-locate");
if (n && n.length === 1) {
n[0].classList += " mapnavigation"
}
});
and the css,
.mapnavigation:before{
display: block;
background: url('mapnavigation.svg');
background-repeat: no-repeat;
background-size: 17px 17px;
background-color: #ffffff;
}

You were really close to the solution, you just need to make it the only class of the node. Take a look at the example I put for you,
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>Locate button | Sample | ArcGIS API for JavaScript 4.18</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.18/esri/themes/light/main.css" />
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
.my-svg-icon {
background: url(https://openlayers.org/en/latest/examples/data/square.svg);
width: 20px;
height: 20px;
}
</style>
<script src="https://js.arcgis.com/4.18/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/widgets/Locate"
], function (Map, MapView, Locate) {
var map = new Map({
basemap: "topo-vector"
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [-56.049, 38.485, 78],
zoom: 3
});
var locateBtn = new Locate({
view: view
});
// Add the locate widget to the top left corner of the view
view.ui.add(locateBtn, {
position: "top-left"
});
view.when(_ => {
const n = document.getElementsByClassName("esri-icon-locate");
if (n && n.length === 1) {
n[0].classList = 'my-svg-icon';
}
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>

Related

How to get data out of a popup on a map with a feature layer from ArcGIS-api for javascript and reuse that data?

I am using a map with feature layers from ArcGIS and the popup to see some data when the user click on a symbol (feature). Is there a way to style the popups exactly the way we want ? In other words, how could I get the data out of the popup, not display the popup but open a modal with that data instead ? Is that even possible ?
This are actually two questions, can you style the popup?, and can you use your own "popup"?.
For the first one, I would say it is pretty customizable, but obviously it depends what you need.
For the second, you just need to stop the default behavior of the view popup, that is to open on right click, and then catch the event yourself to do what you want. Here is an example I made for you that shows that,
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>PopupTemplate - Auto Open False</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.21/esri/themes/light/main.css" />
<script src="https://js.arcgis.com/4.21/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 500px;
width: 100%;
}
#features {
margin: 20px;
height: 500px;
width: 100%;
overflow: auto;
}
</style>
<script>
var populationChange;
require(["esri/Map", "esri/views/MapView", "esri/layers/Layer"], function (
Map,
MapView,
Layer
) {
const map = new Map({
basemap: "dark-gray"
});
const view = new MapView({
container: "viewDiv",
map: map,
zoom: 7,
center: [-87, 34]
});
Layer.fromPortalItem({
portalItem: {
id: "e8f85b4982a24210b9c8aa20ba4e1bf7"
}
}).then(function (layer) {
map.add(layer);
view.popup.autoOpenEnabled = false; // <- disable view popup auto open
view.on("click", function (event) { // <- listen to view click event
if (event.button === 0) { // <- check that was left button or touch
view.whenLayerView(layer).then(function (layerView) {
const query = layerView.layer.createQuery();
query.geometry = view.toMap(event);
query.distance = 1;
query.units = "meters";
layerView.queryFeatures(query).then(
response => {
document.getElementById("features").innerText = JSON.stringify(response.features);
console.error(response);
},
err => {
document.getElementById("features").innerText = "Query returns an error, check console to see what happen!.";
console.error(err);
}
);
});
}
});
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="features"></div>
</body>
</html>

arcGIS 4.18 locate widget custom icon

I have to change the default icon on the Locate widget on arcGIS 4.18. The default icon class is, esri-icon-locate how can I change it to the class, 'esri-icon-navigation'?
I am going through the documentation,
https://developers.arcgis.com/javascript/latest/api-reference/esri-widgets-Locate.html#iconClass
I have tried to use the property, 'iconClass'. But not reflecting in the map icon. Please find the code below,
var locateBtn = new Locate({
view: view,
// iconClass: '\ue666'
iconClass: 'esri-icon-navigation'
});
view.ui.add(locateBtn, {
position: "manual",
});
KER,
You actually right, does not work as expected. Setting iconClass should be the solution.
Funny fact if you check the default iconClass is actually esri-icon-north-navigation, which obviously in not.
Anyway, I am gonna give a dirty solution, just overlap the class you want,
view.when(_ => {
const n = document.getElementsByClassName("esri-icon-locate");
if (n && n.length === 1) {
n[0].classList += " esri-icon-navigation"
}
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no" />
<title>Locate button | Sample | ArcGIS API for JavaScript 4.18</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.18/esri/themes/light/main.css" />
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
</style>
<script src="https://js.arcgis.com/4.18/"></script>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/widgets/Locate"
], function (Map, MapView, Locate) {
var map = new Map({
basemap: "topo-vector"
});
var view = new MapView({
container: "viewDiv",
map: map,
center: [-56.049, 38.485, 78],
zoom: 3
});
var locateBtn = new Locate({
view: view
});
// Add the locate widget to the top left corner of the view
view.ui.add(locateBtn, {
position: "top-left"
});
view.when(_ => {
const n = document.getElementsByClassName("esri-icon-locate");
if (n && n.length === 1) {
n[0].classList += " esri-icon-navigation"
}
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
</body>
</html>

Esri Arc Online using API to see filter result into a simple web page

I need to create a simple webpage where I can see the result of filters in arc online into it instead of creating the filter each day. By that, the results will be refreshed automatically each day when I log in into arc gis.
I heard that there is an API, is my idea is feasible ?
Assuming you want to filter a FeatureLayer--the original question is unclear, but FeatureLayer seems logical--you should set the definitionExpression property, as described in the FeatureLayer documentation.
Here's an example:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scalable=no">
<title>FeatureLayer - 4.3</title>
<link rel="stylesheet" href="https://js.arcgis.com/4.3/esri/css/main.css">
<script src="https://js.arcgis.com/4.3/"></script>
<style>
html,
body,
#viewDiv {
padding: 0;
margin: 0;
height: 100%;
width: 100%;
}
#filterDiv {
position: absolute;
top: 12px;
right: 12px;
padding: 12px;
background-color: rgba(0, 0, 0, 0.5);
color: white;
}
</style>
<script>
require([
"esri/Map",
"esri/views/MapView",
"esri/layers/FeatureLayer",
"dojo/dom",
"dojo/on",
"dojo/domReady!"
],
function(
Map,
MapView,
FeatureLayer,
dom,
on
) {
var map = new Map({
basemap: "hybrid"
});
var view = new MapView({
container: "viewDiv",
map: map,
extent: {
xmin: -9177811,
ymin: 4247000,
xmax: -9176791,
ymax: 4247784,
spatialReference: 102100
}
});
var featureLayer = new FeatureLayer({
url: "https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/Landscape_Trees/FeatureServer/0",
definitionExpression: "Sci_Name = 'Ulmus pumila'"
});
map.add(featureLayer);
view.then(function() {
on(dom.byId("filterInput"), "change", updateFilter);
function updateFilter(ev) {
featureLayer.definitionExpression = ev.target.checked ?
"Sci_Name = 'Ulmus pumila'" :
undefined;
}
});
});
</script>
</head>
<body>
<div id="viewDiv"></div>
<div id="filterDiv">
<label>Filter
<input id="filterInput" type="checkbox" checked="yes">
</label>
</div>
</body>
</html>

Uncaught TypeError: Cannot read property 'on' of undefined in arcgis

i am trying to display navigation tool and switch base map.Individually both are working good when i combine it its showing Uncaught Type Error: Cannot read property 'on' of undefined.can any tell me what is the mistake
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no"/>
<title></title>
<link rel="stylesheet" href="https://js.arcgis.com/3.15/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.15/esri/css/esri.css">
<style>
html, body, #map { height: 100%; width: 100%; margin: 0; padding: 0; }
#switch{
position:absolute;
right:20px;
top:10px;
z-Index:999;
}
#basemapGallery{
width:380px;
height:280px;
}
#HomeButton {
position: absolute;
top: 95px;
left: 20px;
z-index: 50;
}
#navToolbar{
display: block;
position: absolute;
z-index: 2;
top: 10px;
left:2px
}
.zoominIcon {
display: block;
position: absolute;
width: 16px;
height: 16px;
}
.zoomoutIcon {
position: absolute;
width: 16px;
height: 16px;
}
.zoomfullextIcon {
position: absolute;
width: 16px;
height: 16px;
}
.zoomprevIcon {
position: absolute;
width: 16px;
height: 16px;
}
.zoomnextIcon {
position: absolute;
width: 16px;
height: 16px;
}
.panIcon {
position: absolute;
width: 16px;
height: 16px;
}
.deactivateIcon {
position: absolute;
width: 16px;
height: 16px;
}
</style>
<script src="https://js.arcgis.com/3.15/"></script>
<script>
var map;
require([
"esri/map",
"esri/dijit/BasemapGallery",
"esri/dijit/HomeButton",
"esri/toolbars/navigation",
"dojo/on",
"dojo/parser",
"dijit/registry",
"dijit/Toolbar",
"dijit/form/Button",
"dojo/domReady!"
], function(
Map,
BasemapGallery,
HomeButton,
Navigation,
on,
parser,
registry
) {
parser.parse();
var navToolbar;
map = new Map("map", {
basemap: "topo",
center: [-105.255, 40.022],
zoom: 13,
slider:false
});
//add the basemap gallery, in this case we'll display maps from ArcGIS.com including bing maps
var basemapGallery = new BasemapGallery({
showArcGISBasemaps: true,
map: map
}, "basemapGallery");
basemapGallery.on('load',function(){
basemapGallery.remove('basemap_1');
basemapGallery.remove('basemap_2');
basemapGallery.remove('basemap_3');
basemapGallery.remove('basemap_4');
basemapGallery.remove('basemap_5');
basemapGallery.remove('basemap_8');
});
basemapGallery.startup();
basemapGallery.on("error", function(msg) {
console.log("basemap gallery error: ", msg);
});
var home = new HomeButton({
map: map
}, "HomeButton");
home.startup();
navToolbar = new Navigation(map);
on(navToolbar, "onExtentHistoryChange", extentHistoryChangeHandler);
registry.byId("zoomin").on("click", function () {
navToolbar.activate(Navigation.ZOOM_IN);
});
registry.byId("zoomout").on("click", function () {
navToolbar.activate(Navigation.ZOOM_OUT);
});
registry.byId("zoomfullext").on("click", function () {
navToolbar.zoomToFullExtent();
});
registry.byId("zoomprev").on("click", function () {
navToolbar.zoomToPrevExtent();
});
registry.byId("zoomnext").on("click", function () {
navToolbar.zoomToNextExtent();
});
registry.byId("pan").on("click", function () {
navToolbar.activate(Navigation.PAN);
});
registry.byId("deactivate").on("click", function () {
navToolbar.deactivate();
});
function extentHistoryChangeHandler () {
registry.byId("zoomprev").disabled = navToolbar.isFirstExtent();
registry.byId("zoomnext").disabled = navToolbar.isLastExtent();
}
});
</script>
</head>
<body class="claro">
<div id="map">
<div id="navToolbar" data-dojo-type="dijit/Toolbar">
<div data-dojo-type="dijit/form/Button" id="zoomin" data-dojo-props="iconClass:'zoominIcon'">Zoom In</div>
<div data-dojo-type="dijit/form/Button" id="zoomout" data-dojo-props="iconClass:'zoomoutIcon'">Zoom Out</div>
<div data-dojo-type="dijit/form/Button" id="zoomfullext" data-dojo-props="iconClass:'zoomfullextIcon'">Full Extent</div>
<div data-dojo-type="dijit/form/Button" id="zoomprev" data-dojo-props="iconClass:'zoomprevIcon'">Prev Extent</div>
<div data-dojo-type="dijit/form/Button" id="zoomnext" data-dojo-props="iconClass:'zoomnextIcon'">Next Extent</div>
<div data-dojo-type="dijit/form/Button" id="pan" data-dojo-props="iconClass:'panIcon'">Pan</div>
<div data-dojo-type="dijit/form/Button" id="deactivate" data-dojo-props="iconClass:'deactivateIcon'">Deactivate</div>
</div>
<div id="HomeButton"></div>
<div id="switch" data-dojo-type="dijit/TitlePane" data-dojo-props="title:'Switch Basemap', closable:false, open:false">
<div id="basemapGallery"></div>
</div>
</div>
</body>
</html>
parser.parse returns a deferred in dojo 1.8+
what this means is that after
parser.parse()
your widgets are not necessarily instantiated and ready to be referenced as widgets via dijit/registry.
Also there is this is directly from the Dojo reference guide:
Note that waiting for dojo/domReady! to fire is often not sufficient when working with widgets. Many widgets shouldn’t be initialized or accessed until the following modules load and execute:
dojo/uacss
dijit/hccss
dojo/parser
Thus when working with widgets you should generally put your code inside of a dojo/ready() callback:
you do this by including "dojo/ready" in your require array and then wrapping any widget code in
ready(function(){
...your widget code....
})
in your case you could probably just wrap your entire javascript code in a ready function
require([
"esri/map",
"esri/dijit/BasemapGallery",
"esri/dijit/HomeButton",
"esri/toolbars/navigation",
"dojo/on",
"dojo/parser",
"dijit/registry",
"dojo/ready",
"dijit/Toolbar",
"dijit/form/Button",
"dojo/domReady!"
], function(
Map,
BasemapGallery,
HomeButton,
Navigation,
on,
parser,
registry,
ready
) {
ready(function() {
var navToolbar;
map = new Map("map", {
basemap: "topo",
center: [-105.255, 40.022],
zoom: 13,
slider: false
});
...etc
I also like to use parseOnLoad = true which I find to be less prone to errors (both human and otherwise)
Just put this script element above the arcgis js script tag like so
<script type="text/javascript">
var dojoConfig = {
parseOnLoad: true
};
</script>
<script src="https://js.arcgis.com/3.15/"></script>
and get rid of the call to parser.parse() at the top of your script.

Restricting results when using google.maps.FusionTablesLayer

My map is showing all of the data in a fusion table when I would like to restrict it.
Also, how would I query by the 'Geographic Name' field? I tried the query below but it would not work.
***Edit I solved the problem below by using code similar to this:
select: 'State Abbr.',
from: '1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa',
where: "'State Abbr.' = 'FL'",
The issue was the lack of quotations.
Any assistance is appreciated!
select: 'State-County',
from: '1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa',
where: 'State-County = AL-Autauga'
Here is my code currently:
****Edit: I have fixed the issue below by updating the code as follows
query: {
select: 'GEO_ID',
from: '1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa',
where: "GEO_ID = '05000US01001'"
},
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<title>Geocoding service</title>
<style>
html, body, #map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
#panel {
position: absolute;
top: 5px;
left: 50%;
margin-left: -180px;
z-index: 5;
background-color: #fff;
padding: 5px;
border: 1px solid #999;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true"></script>
<script>
var geocoder;
var map;
var layer;
function initialize() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(34.0754, -84.2946);
var mapOptions = {
zoom: 8,
center: latlng
}
map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
}
function codeAddress() {
var address = document.getElementById('address').value;
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
layer = new google.maps.FusionTablesLayer({
query: {
select: 'GEO_ID',
from: '1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa',
where: 'GEO_ID = 05000US01001'
},
supressInfoWindows: true,
styles: [
{polygonOptions: {fillColor:'#0040FF',fillOpacity:0.1,strokeColor:'#FF0000',strokeWeight:2,strokeOpacity:0.6 }}
]
});
layer.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="panel">
<input id="address" type="textbox" value="Alpharetta, Georgia">
<input type="button" value="Geocode" onclick="codeAddress()">
</div>
<div id="map-canvas"></div>
</div>
</body>
</html>
Link to Fusion Table: https://www.google.com/fusiontables/data?docid=1xdysxZ94uUFIit9eXmnw1fYc6VcQiXhceFd_CVKa#rows:id=3