Currently I am building a web Application using ArcGIS Javascript API.
Where I can add marker to the map graphics, on adding marker request I am setting few attributes to that marker using Popup Template like this
map.graphics.add(new Graphic(evt.geometry, symbol, PointAtt, popupTemplate));
Here I want to ask, how I can edit these attributes at Map Runtime because I want to do some changes in the attributes.
<script src="https://js.arcgis.com/3.17/"></script>
<script>
var map, tb;
var otherWindow;
var PointAtt = {};
require([
"esri/map",
"esri/toolbars/draw",
"esri/dijit/PopupTemplate",
"esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleLineSymbol",
"esri/symbols/PictureFillSymbol", "esri/symbols/CartographicLineSymbol",
"esri/graphic",
"esri/Color", "dojo/dom", "dojo/on",
"dojo/domReady!"
], function (
Map, Draw, PopupTemplate,
SimpleMarkerSymbol, SimpleLineSymbol,
PictureFillSymbol, CartographicLineSymbol,
Graphic,
Color, dom, on) {
map = new Map("mapDiv", {
basemap : "streets",
center : [-25.312, 34.307],
zoom : 3
});
otherWindow = window.open("integrationPage.html", "otherWindow");
map.on("load", initToolbar);
// markerSymbol is used for point and multipoint, see http://raphaeljs.com/icons/#talkq for more examples
var markerSymbol = new SimpleMarkerSymbol();
markerSymbol.setPath("M16,4.938c-7.732,0-14,4.701-14,10.5c0,1.981,0.741,3.833,2.016,5.414L2,25.272l5.613-1.44c2.339,1.316,5.237,2.106,8.387,2.106c7.732,0,14-4.701,14-10.5S23.732,4.938,16,4.938zM16.868,21.375h-1.969v-1.889h1.969V21.375zM16.772,18.094h-1.777l-0.176-8.083h2.113L16.772,18.094z");
markerSymbol.setColor(new Color("#00FFFF"));
// lineSymbol used for freehand polyline, polyline and line.
var lineSymbol = new CartographicLineSymbol(
CartographicLineSymbol.STYLE_SOLID,
new Color([255, 0, 0]), 10,
CartographicLineSymbol.CAP_ROUND,
CartographicLineSymbol.JOIN_MITER, 5);
// fill symbol used for extent, polygon and freehand polygon, use a picture fill symbol
// the images folder contains additional fill images, other options: sand.png, swamp.png or stiple.png
var fillSymbol = new PictureFillSymbol(
"images/mangrove.png",
new SimpleLineSymbol(
SimpleLineSymbol.STYLE_SOLID,
new Color('#000'),
1),
42,
42);
function initToolbar() {
tb = new Draw(map);
tb.on("draw-end", addGraphic);
// Get Marker Click Event
map.graphics.on("click", function (evt) {
// alert("Marker Clicked");
var lat = evt.mapPoint.getLatitude();
var lon = evt.mapPoint.getLongitude();
var sendEvent = [];
sendEvent[0] = evt.graphic.attributes.ID;
sendEvent[1] = evt.mapPoint.getLatitude();
sendEvent[2] = evt.mapPoint.getLongitude();
// Sending event to other html page
otherWindow.postMessage(sendEvent, "http://localhost:9090");
});
// event delegation so a click handler is not
// needed for each individual button
on(dom.byId("info"), "click", function (evt) {
if (evt.target.id === "info") {
return;
}
var tool = evt.target.id.toLowerCase();
map.disableMapNavigation();
tb.activate(tool);
});
}
function addGraphic(evt) {
// deactivate the toolbar and clear existing graphics
tb.deactivate();
map.enableMapNavigation();
var sendEvent = []; // Array which is sent to other sources
var counter = 0;
sendEvent[0] = "added"
sendEvent[1] = evt.geometry.getLatitude();
sendEvent[2] = evt.geometry.getLongitude();
otherWindow.postMessage(sendEvent, "http://localhost:9090");
// Marker ID is being received from the Key Generator
window.addEventListener("message", function (event) {
var receivedEvent;
console.log("onMessage::" + event.data);
receivedEvent = event.data;
if (receivedEvent[0] == "added" && counter == 0) {
PointAtt = {
Name : "Islamabad", // The name of the pipeline
Type : "City", // The owner of the pipeline
ID : receivedEvent[1],// The length of the pipeline
Latitude : evt.geometry.getLatitude(),
Longitude: evt.geometry.getLongitude()
};
var popupTemplate = new PopupTemplate({
title : "{*}", // The title of the popup will be the name of the pipeline
content : "{*}" // Displays a table of all the attributes in the popup
})
// figure out which symbol to use
var symbol;
if (evt.geometry.type === "point" || evt.geometry.type === "multipoint") {
symbol = markerSymbol;
} else if (evt.geometry.type === "line" || evt.geometry.type === "polyline") {
symbol = lineSymbol;
} else {
symbol = fillSymbol;
}
map.graphics.add(new Graphic(evt.geometry, symbol, PointAtt, popupTemplate));
counter = counter + 1;
event.data = "";
}
}, false);
}
});
you can use esri AttributeInspector for this. Though it works for feature layers to but you can customize it accordingly.
Either you can create feature layer on the map and add graphics to it and pass that to layerInfos OR you can override the attribute inspector so support graphics layer too.
Use Below code for this-
//add a save button next to the delete button
var saveButton = new Button({ label: "Save", "class": "saveButton"},domConstruct.create("div"));
domConstruct.place(saveButton.domNode, attInspector.deleteBtn.domNode, "after");
saveButton.on("click", function() {
updateFeature.getLayer().applyEdits(null, [updateFeature], null);
});
attInspector.on("attribute-change", function(evt) {
//store the updates to apply when the save button is clicked
updateFeature.attributes[evt.fieldName] = evt.fieldValue;
});
attInspector.on("next", function(evt) {
updateFeature = evt.feature;
console.log("Next " + updateFeature.attributes.OBJECTID);
});
For attribute inspector please click here...
Here is the working code for feature layer-
<!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>Editable FeatureLayer with Attribute Inspector</title>
<link rel="stylesheet" href="https://js.arcgis.com/3.18/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.18/esri/css/esri.css">
<style>
html, body, #mapDiv{
height: 100%;
width: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
#detailPane{
padding: 6px;
height:20px;
color:#570026;
font-size:12pt;
font-weight:600;
overflow: hidden;
}
.dj_ie .infowindow .window .top .right .user .content { position: relative; }
.dj_ie .simpleInfoWindow .content {position: relative;}
.esriAttributeInspector .atiLayerName {display:none;}
</style>
<script src="https://js.arcgis.com/3.18/"></script>
<script>
var map, updateFeature;
require([
"esri/map",
"esri/layers/FeatureLayer",
"esri/dijit/AttributeInspector",
"esri/symbols/SimpleLineSymbol",
"esri/symbols/SimpleMarkerSymbol",
"esri/Color",
"esri/renderers/UniqueValueRenderer",
"esri/config",
"esri/tasks/query",
"dojo/dom-construct",
"dijit/form/Button",
"dojo/domReady!"
], function(
Map, FeatureLayer, AttributeInspector,
SimpleLineSymbol, SimpleMarkerSymbol, Color, UniqueValueRenderer,
esriConfig,
Query, domConstruct, Button
) {
// refer to "Using the Proxy Page" for more information: https://developers.arcgis.com/javascript/3/jshelp/ags_proxy.html
esriConfig.defaults.io.proxyUrl = "/proxy/";
map = new Map("mapDiv", {
basemap: "dark-gray",
center: [-97.395, 37.537],
zoom: 5
});
map.on("layers-add-result", initSelectToolbar);
//Feature Layer representing 2015 men's NCAA basketball tournament teams
var teamsFL = new FeatureLayer("https://services.arcgis.com/V6ZHFr6zdgNZuVG0/arcgis/rest/services/NCAA_Tourney_2015/FeatureServer/1", {
outFields: ["University", "WINPER", "Rd_64_Venue", "Rd_64_Result", "Rd_64_Margin"]
});
var selectionSymbol = new SimpleMarkerSymbol(
SimpleMarkerSymbol.STYLE_CIRCLE, 6,
new SimpleLineSymbol(
"solid",
new Color([255,0,0,0.5]),
4
),
new Color("#ED3939")
);
var defaultSymbol = new SimpleMarkerSymbol(
SimpleMarkerSymbol.STYLE_CIRCLE, 7,
null,
new Color([255,255,255])
);
teamsFL.setSelectionSymbol(selectionSymbol);
//Symbolize features by W/L record
var recordRenderer = new UniqueValueRenderer(defaultSymbol, "Rd_64_Result");
recordRenderer.addValue("W", new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 7, null, new Color([93,240,79])));
recordRenderer.addValue("L", new SimpleMarkerSymbol(SimpleMarkerSymbol.STYLE_CIRCLE, 7, null, new Color([240,146,79])));
teamsFL.setRenderer(recordRenderer);
map.addLayers([teamsFL]);
function initSelectToolbar(evt) {
var teamsFL = evt.layers[0].layer;
var selectQuery = new Query();
map.on("click", function(evt) {
selectQuery.geometry = evt.mapPoint;
selectQuery.distance = 50;
selectQuery.units = "miles"
selectQuery.returnGeometry = true;
teamsFL.selectFeatures(selectQuery, FeatureLayer.SELECTION_NEW, function(features) {
if (features.length > 0) {
//store the current feature
updateFeature = features[0];
map.infoWindow.setTitle(features[0].getLayer().name);
map.infoWindow.show(evt.screenPoint, map.getInfoWindowAnchor(evt.screenPoint));
}
else {
map.infoWindow.hide();
}
});
});
map.infoWindow.on("hide", function() {
teamsFL.clearSelection();
});
var layerInfos = [
{
'featureLayer': teamsFL,
'showAttachments': false,
'isEditable': true,
'fieldInfos': [
{'fieldName': 'University', 'isEditable': false, 'label': 'School:'},
{'fieldName': 'WINPER', 'isEditable': true, 'tooltip': 'Win percentage', 'label': 'Win percentage:'},
{'fieldName': 'Rd_64_Venue', 'isEditable': false, 'label': 'Rd 1 Venue:'},
{'fieldName': 'Rd_64_Result', 'isEditable': true, 'tooltip': 'First round result (W/L)', 'label': 'Rd 1 Result:'},
{'fieldName': 'Rd_64_Margin', 'isEditable': true, 'tooltip': 'First round margin of victory/loss', 'label': 'Rd 1 Margin:'}
]
}
];
//Initialize Attribute Inspector
var attInspector = new AttributeInspector({
layerInfos: layerInfos
}, domConstruct.create("div"));
//add a save button next to the delete button
var saveButton = new Button({ label: "Save", "class": "saveButton"},domConstruct.create("div"));
domConstruct.place(saveButton.domNode, attInspector.deleteBtn.domNode, "after");
saveButton.on("click", function() {
updateFeature.getLayer().applyEdits(null, [updateFeature], null);
});
attInspector.on("attribute-change", function(evt) {
//store the updates to apply when the save button is clicked
updateFeature.attributes[evt.fieldName] = evt.fieldValue;
});
attInspector.on("next", function(evt) {
updateFeature = evt.feature;
console.log("Next " + updateFeature.attributes.OBJECTID);
});
attInspector.on("delete", function(evt) {
evt.feature.getLayer().applyEdits(null, null, [evt.feature]);
map.infoWindow.hide();
});
map.infoWindow.setContent(attInspector.domNode);
map.infoWindow.resize(350, 240);
}
});
</script>
</head>
<body class="claro">
<div id="detailPane">
Click to display the attribute inspector for all NCAA men's basketball tournament teams within 50 miles of click.
</div>
<div id="mapDiv"></div>
</body>
</html>
Output:-
Well, It seems quite straight forward to implement. You can use setter method of attribute for it. It will direct update the existing attributes/Values of feature on the map.
Use Below code for it-
var attributeObject = {"name":"updatedNmme","value":"updatedValue"};
graphicsObject.setAttributes(attributeObject );
Note- It will remove all the existing attributes and add new attributes(attributeObject ) to the graphics so if you want to keep some of the existing attributes as it is then pass those values also in attributeObject.
For complete reference please click here...
Hoping this will help you :)
P.S. It is always recommended to add complete code here if you are expecting the exact fix. However above code will fix your problem.
Related
Using Leaflet, I linked to a L.easyButton a function which adds a geoJson polygon layer to a map, and that activates different functions "onEachFeature" of this layer. Among them, a function when clicking on a feature which creates a separate geoJson polygon layer with this feature and add it to a specific LayerGroup. What I would like is that after clicking on a feature, the different functions "onEachFeature" would not be activated anymore and that the user would need to push the L.easyButton again if he/she wants to do that another time. Everything works fine, except the fact to deactivate the "onEachFeature" functions. I tried to use map.removeControl(), map.removeLayer() and delete the variable directly, but none of these options work.
My code is:
L.easyButton( '<strong>Sélectionner une commune</strong>', function(){
var communes_geojson = $.getJSON("data/Adm/Adm_Communes_4326.geojson",function(communes){
var communes_new = L.geoJson(communes, {
style: stylelayer.communes,
onEachFeature: function addMyData (feature,layer){
layer.on({
click: selectcommune
});
}
});
map.addControl(communes_new);
});
info.addTo(map);
},
{position: 'topright'}).addTo(map);
function selectcommune(e) {
var layer=e.target;
var feature = e.target.feature;
var selectcommune1 = L.geoJson(feature, {
style: stylelayer.highlight
}).addTo(map);
control_map2.addOverlay({
name:feature.properties.NameFRE,
layer:selectcommune1
});
// don't work
// map.removeControl(communes_geojson);
// map.removeControl(communes_new);
// map.removeControl(layer);
// map.removeLayer(communes_geojson);
// map.removeLayer(communes_new);
// map.removeLayer(layer);
// delete communes_geojson;
// delete communes_new;
// delete layer;
Tahnk you for your help.
In selectcommune, once you do what you want (style your feature and add your overlay), you then need to go back and void out the onEachFeature function that you had added with the L.easyButton:
L.easyButton( '<strong>Sélectionner une commune</strong>', function(){
var communes_geojson = $.getJSON("data/Adm/Adm_Communes_4326.geojson",function(communes){
var communes_new = L.geoJson(communes, {
style: stylelayer.communes,
onEachFeature: function addMyData (feature,layer){
layer.on({
click: e => selectcommune(e, communes_new)
});
}
});
map.addControl(communes_new);
});
info.addTo(map);
},
function selectcommune(e, data) {
var layer=e.target;
var feature = e.target.feature;
var selectcommune1 = L.geoJson(feature, {
style: stylelayer.highlight
}).addTo(map);
control_map2.addOverlay({
name:feature.properties.NameFRE,
layer:selectcommune1
});
data.eachLayer( layer => layer.on = () => {} )
}
So you hit the easybutton, and layer.on is set for each feature to fire the selectcommune. When it fires, it removes the layer.on function (or overwrites it to do nothing), until you hit the easybutton again.
I've embedded a Google Map into my application. Interacting with the map works. Responding to map events works (map zoom_changed, marker dragend, etc). However, only some parts of the map are visible (the marker and the Google logo for example), but the maps themselves are not (at least they don't appear 95% of the time).
Can anyone tell me what's going on here?
EDIT: I'm using this as a KnockoutJS component (inserted with with <gui-map></gui-map>). The source code below. I don't believe the use of KnockoutJS has anything to do with the map issues because: a) all the observables are wired up correctly and working 100% of the time; and b) the map does work randomly without any code changes 5% of the time.
define(['knockout', 'underscore'], function(ko, _){
function Map(params, componentInfo) {
var self = this;
var defaultPosition = {lat:-25,lng:-130};
var width = ko.isObservable(params.width) ? params.width : ko.observable(params.width ? params.width : '100px');
var height = ko.isObservable(params.height) ? params.height : ko.observable(params.height ? params.height : '100px');
var center = ko.isObservable(params.center) ? params.center : ko.observable(params.center ? params.center : defaultPosition);
var zoom = ko.isObservable(params.zoom) ? params.zoom : ko.observable(params.zoom ? params.zoom : 12);
var marker = ko.isObservable(params.marker) ? params.marker : ko.observable(params.marker ? params.marker : defaultPosition);
var element = componentInfo.element;
element.style.display = 'block';
element.style.width = width();
element.style.height = height();
width.subscribe(function(){
element.style.width = width();
});
height.subscribe(function(){
element.style.height = height();
});
function onObservableCenterChanged(newValue){
onObservableCenterChanged.changing = 1;
console.log('updating center map');
map.setCenter(newValue);
setTimeout(function(){
onObservableCenterChanged.changing = 0;
}, 500);
}
center.subscribe(onObservableCenterChanged);
function onObservableZoomChanged(newValue){
onObservableZoomChanged.changing = 1;
console.log('updating map zoom');
map.setZoom(newValue);
setTimeout(function(){
onObservableZoomChanged.changing = 0;
}, 500);
}
zoom.subscribe(onObservableZoomChanged);
var map = new google.maps.Map(element, {
center: center(),
zoom: zoom()
});
var mapMarker = new google.maps.Marker({
position:center(),
map:map,
title:'',
draggable:true
});
map.addListener('center_changed', (function(){
var mapCenterChangeTimeout;
return function(){
if (mapCenterChangeTimeout) {
clearTimeout(mapCenterChangeTimeout);
}
mapCenterChangeTimeout = setTimeout(function(){
if (!onObservableCenterChanged.changing) {
var newCenter = map.getCenter();
console.log('updating center observble');
center({
lat:newCenter.lat(),
lng:newCenter.lng()
});
}
}, 500);
};
})());
map.addListener('zoom_changed', (function(){
var mapZoomChangedTimeout;
return function(){
if (mapZoomChangedTimeout) {
clearTimeout(mapZoomChangedTimeout);
}
mapZoomChangedTimeout = setTimeout(function(){
if (!onObservableZoomChanged.changing) {
console.log('updating zoom observable');
zoom(map.getZoom());
}
}, 500);
};
})());
mapMarker.addListener('dragend', function(){
var newPosition = mapMarker.getPosition();
marker({
lat:newPosition.lat(),
lng:newPosition.lng()
});
});
}
ko.components.register('gui-map', {
template:{
require:'text!components/gui/map.html'
},
viewModel:{
createViewModel:function(params, componentInfo){
return new Map(params, componentInfo);
}
}
});
});
EDIT2: I have succesfully got the above to work by wrapping the entire body of the Map function (with exception of the var self = this; assignment) in a anonymous function called with setTimeout() (with a delay of 5000 ms). However, all the code executes after the DOMContentLoaded event anyway, so I'm not sure why this is an issue.
The cause of the problem was that the Google Maps Javascript API does NOT render the map correctly if the element in which the map is contained is not visible. In my situation, the map was located in a hidden tab. The timeout mentioned above solved the problem because the delay gave me long enough to switch tabs before the function that calls the Google Maps API could be executed (if I delayed opening the tab until after the Google Maps API was called, the issue would re-surface).
I got around this issue by manually triggering a resize on the map, and manually updating the various controls on the map, e.g.:
google.maps.event.trigger(map, 'resize');
infoWindow.setContent(infoWindowElement);
infoWindow.close();
infoWindow.open(map, marker);
I hope this solution helps someone else.
I working on a project trying to add feature layers from ArcGIS online to a web map application using the JavaScript API where a user can toggle the layers on and off through a HTML tick box. The layers are importing correctly and are displayed when the tick boxes are bypassed but I can get it to work with the tickboxes. I have hacked code from ArcGIS samples etc so it must be some small thing I keep missing!
Here is the code - basically all I want is the layers to toggle on and off on top of a constant base map based on which checkboxes the user ticks on and off
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<!--The viewport meta tag is used to improve the presentation and behavior of the samples
on iOS devices-->
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Select with feature layer</title>
<link rel="stylesheet" href="http://js.arcgis.com/3.10/js/dojo/dijit/themes/tundra/tundra.css">
<link rel="stylesheet" href="http://js.arcgis.com/3.10/js/esri/css/esri.css">
<style>
html, body, #mapDiv {
padding: 0;
margin: 0;
height: 100%;
}
#messages{
background-color: #fff;
box-shadow: 0 0 5px #888;
font-size: 1.1em;
max-width: 15em;
padding: 0.5em;
position: absolute;
right: 20px;
top: 20px;
z-index: 40;
}
</style>
<script src="http://js.arcgis.com/3.10/"></script>
<script>
var map;
require([
"esri/map", "esri/layers/FeatureLayer",
"esri/tasks/query", "esri/geometry/Circle",
"esri/graphic", "esri/InfoTemplate", "esri/symbols/SimpleMarkerSymbol",
"esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleFillSymbol", "esri/renderers/SimpleRenderer",
"esri/config", "esri/Color", "dojo/dom", "dojo/domReady!", "dojo/on", "dojo/query", "dojo/domReady!", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/layers/ImageParameters",
], function (
Map, FeatureLayer,
Query, Circle,
Graphic, InfoTemplate, SimpleMarkerSymbol,
SimpleLineSymbol, SimpleFillSymbol, SimpleRenderer,
esriConfig, Color, dom, on, query, ArcGISDynamicMapServiceLayer, ImageParameters
) {
// use a proxy page if a URL generated by this page is greater than 2000 characters
//
// this should not be needed as nearly all query & select functions are performed on the client
esriConfig.defaults.io.proxyUrl = "/proxy";
map = new Map("mapDiv", {
basemap: "streets",
center: [-120.303130, 36.542750],
zoom: 5,
slider: false
});
//add the census block points in on demand mode. Note that an info template has been defined so when
//selected features are clicked a popup window will appear displaying the content defined in the info template.
var Offices = new FeatureLayer("URL", {
infoTemplate: new InfoTemplate("Block: ${BLOCK}", "${*}"),
outFields: ["*"]
});
var Northridge = new FeatureLayer("URL", {
infoTemplate: new InfoTemplate("Block: ${BLOCK}", "${*}"),
outFields: ["*"]
});
var Associates = new FeatureLayer("URL", {
infoTemplate: new InfoTemplate("Block: ${BLOCK}", "${*}"),
outFields: ["*"]
});
// selection symbol used to draw the selected census block points within the buffer polygon
var symbol = new SimpleMarkerSymbol(
SimpleMarkerSymbol.STYLE_CIRCLE,
12,
new SimpleLineSymbol(
SimpleLineSymbol.STYLE_NULL,
new Color([247, 34, 101, 0.9]),
1
),
new Color([207, 34, 171, 0.5])
);
Offices.setSelectionSymbol(symbol);
//make unselected features invisible
var nullSymbol = new SimpleMarkerSymbol().setSize(10);
var RedCircle = new SimpleMarkerSymbol().setSize(8);
Offices.setRenderer(new SimpleRenderer(nullSymbol));
on(dom.byId("layer0CheckBox"), "change", updateLayerVisibility);
on(dom.byId("layer1CheckBox"), "change", updateLayerVisibility);
on(dom.byId("layer2CheckBox"), "change", updateLayerVisibility);
function updateLayerVisibility() {
var inputs = query(".list_item");
var inputCount = inputs.length;
//in this application layer 2 is always on.
visibleLayerIds = [2];
for (var i = 0; i < inputCount; i++) {
if (inputs[i].checked) {
visibleLayerIds.push(inputs[i].value);
}
}
if (visibleLayerIds.length === 0) {
visibleLayerIds.push(-1);
}
map.addLayers(visibleLayerIds);
}
});
</script>
</head>
<body>
<br />
<br />
Layer List : <span id="layer_list"><input type='checkbox' class='list_item' id='layer0CheckBox' value="Northridge" />Earthquake
<input type='checkbox' class='list_item' id='layer1CheckBox' value="Offices" />Offices
<input type='checkbox' class='list_item' id='layer2CheckBox' value="Associates" />Associates
</span><br />
<br />
<div id="mapDiv"></div>
</body>
</html>
Done this long time ago
changeVLayerVisibility: function(names) {
Ext.Array.each(map.graphicsLayerIds, function(id) {
map.getLayer(id).setVisibility(names.indexOf(id) !== -1);
});
},
Check an example here: http://smart-tech-group.com/arcgismap/
The map-related logic is stored in http://smart-tech-group.com/arcgismap/APP/view/ArcMapViewer.js I was a js-newbie back then, so feel free to argue on my code style;)
In function updateLayerVisibility, the map.addLayers usage is wrong.
you should add featurelayers, graphic layers, dynamic layers or tiled layers, not the ids, unless you store them in the array visibleLayerIds.
You may consider use ArcGISDynamicMapServiceLayer to control visible layer ids. Then use setVisibleLayers API see https://developers.arcgis.com/javascript/jsapi/arcgisdynamicmapservicelayer-amd.html
FeatureLayer is usually for a single layer, use service like MapServer/2 or FeatureServer/2.
When I create map object using ArcGISDynamicMapServiceLayer then things work fine but since I need lot of graphics and want to handle user interactions on map so I want to feature layer to my map but when I add feature layer the browser hangs.
Please let me know what could be the issue how can I avoid feature layer from hanging from my machine. Can I add onclick mouse over functionality for ArcGISDynamicMapServiceLayer
Below is the code
map = new esri.Map("map");
var layer = new esri.layers.ArcGISDynamicMapServiceLayer("http://10.32.9.106:6080/arcgis/rest/services/Administrative_Maps/World_Countries_v1/MapServer");
map.addLayer(layer);
var url = "http://10.32.9.106:6080/arcgis/rest/services/Administrative_Maps/World_Countries_v1/MapServer/0";
var info_content = "<table><tr><td><b>COUNTRY :</b></td><td style='text-align:right'>${COUNTRY}</td></tr></table>";
var infoTemplate1 = new esri.InfoTemplate("${COUNTRY}", info_content);
var fl = new esri.layers.FeatureLayer(url, {
id: "world-regions",
infoTemplate: infoTemplate1
});
map.addLayer(fl);
MY HTML CODE Is below
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=7, IE=9, IE=10">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Feature Layer Only Map</title>
<link rel="stylesheet" href="http://js.arcgis.com/3.6/js/esri/css/esri.css">
<style>
html, body, #map {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script src="http://js.arcgis.com/3.6/"></script>
<script>
dojo.require("esri.map");
dojo.require("esri.layers.FeatureLayer");
dojo.require("esri.tasks.QueryTask");
var map;
function init(){
try{
map = new esri.Map("map");
var layer = new esri.layers.ArcGISDynamicMapServiceLayer("http://10.32.9.106:6080/arcgis/rest/services/Administrative_Maps/World_Countries_v1/MapServer");
map.addLayer(layer);
var url = "http://10.32.9.106:6080/arcgis/rest/services/Administrative_Maps/World_Countries_v1/MapServer/0";
var info_content = "<table><tr><td><b>COUNTRY :</b></td><td style='text-align:right'>${COUNTRY}</td></tr></table>";
var infoTemplate1 = new esri.InfoTemplate("${COUNTRY}", info_content);
var fl = new esri.layers.FeatureLayer(url, {
id: "world-regions",
mode: esri.layers.FeatureLayer.MODE_ONDEMAND,
autoGeneralize :true,
allowGeometryUpdates:false,
infoTemplate: infoTemplate1,
outFields: ["COUNTRY"]
});
dojo.connect(fl, "onLoad", function(){
console.log(" adding feature layer");
fl.setAutoGeneralize(true)
map.addLayer(fl);
console.log("allowGeometryUpdates "+fl.allowGeometryUpdates);
console.log("editable "+fl.isEditable());
console.log("autoGeneralize"+fl.autoGeneralize);
console.log("geometryType"+fl.geometryType);
console.log("graphics"+fl.graphics);
console.log("defaultVisibility "+fl.hasAttachments);
});
var queryTask = new esri.tasks.QueryTask(url);
//build query filter
var query = new esri.tasks.Query();
query.returnGeometry = true;
query.where = "COUNTRY='India'";
infoTemplate = new esri.InfoTemplate("Alert", "Alert for Re-insurance");
dojo.connect(queryTask, "onComplete", function(featureSet) {
alert('calling queryTask'+featureSet);
//map.graphics.clear();
try{
/*var sfs = new SimpleFillSymbol(SimpleFillSymbol.STYLE_FORWARD_DIAGONAL, new SimpleLineSymbol(SimpleLineSymbol.STYLE_SOLID, new Color([255, 0, 0]), 2), new Color([255, 255, 0, 0.5]));
alert('somethign');*/
var symbol0 = new esri.symbol.SimpleFillSymbol().setColor(new dojo.Color([255, 0, 0, 0.9]));
//QueryTask returns a featureSet. Loop through features in the featureSet and add them to the map.
dojo.forEach(featureSet.features,function(feature){
alert('feature'+feature);
var graphic = feature;
graphic.setSymbol(symbol0);
alert("infoTemplate"+infoTemplate);
graphic.setInfoTemplate(infoTemplate);
alert("graphic"+graphic);
alert("map.graphics"+map.graphics);
map.graphics.add(graphic);
});
}catch(e){
alert("e"+e);
}
});
queryTask.execute(query);
require(["dojo/on", "esri/symbols/SimpleFillSymbol", "esri/symbols/SimpleLineSymbol", "dojo/_base/Color", "esri/graphic"], function(on, SimpleFillSymbol, SimpleLineSymbol, Color, Graphic) {
on(fl, "click", function(evt) {
console.log(" on click method");
// clears current selection
map.graphics.clear();
// create new graphic with selected graphic's geometry
alert("evt.graphic.geometry "+evt.graphic.geometry);
var graphic = new Graphic(evt.graphic.geometry);
alert("graphic "+graphic);
// create a new symbol for the graphic
var symbol0 = new esri.symbol.SimpleFillSymbol().setColor(new dojo.Color([255, 0, 0, 0.9]));
// add symbol to the graphic
graphic.setSymbol(symbol0);
// add the graphic to the map
map.graphics.add(graphic);
});
});
} catch(e){
console.log(" exception occured"+e);
}
}
dojo.addOnLoad(init);
</script>
</head>
<body>
<div id="map"></div>
</body>
</html>
The trouble is nearly to come with the amount of data retrieved by the browser and displayed. FeatureLayer is limited in number of detailed features displayed at once.
But the server is helpful at this point, you ask the server to generalize on the fly the geometries. This reduce a lot the geometry volume depending on the scale.
in your code, you can use the setAutoGeneralize(enable) to true on the FeatureLayer.
you can also set a minsccale and maxscale of the feature layer to avoid display the scales on which you have a lot of geometries.
Documentation on FeatureLayer, and setAutoGeneralize method/option
autoGeneralize option in constructor :
autoGeneralize Enable or disable the auto generalization of
features from a non-editable layer in on-demand mode. When true, the
layer uses the current map resolution as the maxAllowableOffset for
all queries issued to the server. The default value is true. As of
v2.7
by using this code to choose the generalization parameter (max allowableOffset), could reduce the amont of datas transferred to the browser, and gaining in user experience.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=7, IE=9, IE=10">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<title>Feature Layer Only Map</title>
<link rel="stylesheet" href="http://js.arcgis.com/3.6/js/esri/css/esri.css">
<style>
html, body, #map {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
}
</style>
<script src="http://js.arcgis.com/3.6/"></script>
<script>
var map;
require(["dojo/on","esri/config", "esri/map", "dojo/domReady!","esri/layers/ArcGISDynamicMapServiceLayer","esri/layers/FeatureLayer","esri/InfoTemplate" ], function(on,config, Map,Ready,ArcGISDynamicMapServiceLayer,FeatureLayer,InfoTemplate) {
config.defaults.io.alwaysUseProxy = true;
config.defaults.io.proxyUrl = "/proxy.jsp";
config.defaults.io.corsEnabledServers.push("sampleserver1.arcgisonline.com");
map = new Map("map", { lods : [
{"level" : 0, "resolution" : 0.010986328125, "scale" : 4617149.97766929},
{"level" : 1, "resolution" : 0.0054931640625, "scale" : 2308574.98883465},
{"level" : 2, "resolution" : 0.00274658203125, "scale" : 1154287.49441732},
{"level" : 3, "resolution" : 0.001373291015625, "scale" : 577143.747208662},
{"level" : 4, "resolution" : 0.0006866455078125, "scale" : 288571.873604331}
]
});
var layer = new ArcGISDynamicMapServiceLayer("http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer");
map.addLayer(layer);
layer.setVisibility(false);
var url = "http://sampleserver1.arcgisonline.com/ArcGIS/rest/services/Demographics/ESRI_Census_USA/MapServer/3";
var info_content = "<table><tr><td><b>COUNTRY :</b></td><td style='text-align:right'>${COUNTRY}</td></tr></table>";
var infoTemplate1 = new InfoTemplate("${STATE_NAME}", info_content);
var fl = new FeatureLayer(url, {
id: "usa-regions",
mode: FeatureLayer.MODE_ONDEMAND,
autoGeneralize:false,
allowGeometryUpdates:false,
infoTemplate: infoTemplate1,
outFields: ["STATE_NAME"],
maxAllowableOffset : 0.02
});
on(map,"zoom-end", function(evt)
{
fl.setMaxAllowableOffset(evt.extent.getWidth() / 400);
});
map.addLayer(fl);
});
</script>
</head>
<body>
<div id="elements"></div>
<div id="map"></div>
</body>
</html>
I have GPS tracking server and problem with clearing markers added with MarkerManager from database. My truncated code:
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml">
<head>
<script src='http://maps.google.com/maps?file=api&v=2&hl=pl&key=my_key' type='text/javascript'></script>
</head>
<body onload='mapStart()' onunload='GUnload()'>
<script type='text/javascript'>
var map;
var mgr=false;
var timeOut=null;
function mapStart()
{
if(GBrowserIsCompatible())
{
map = new GMap2(document.getElementById("map"),{mapTypes: [G_NORMAL_MAP,G_HYBRID_MAP,G_SATELLITE_MAP,G_PHYSICAL_MAP]});
center = new GLatLng(52.536395, 13.42534);
map.setCenter(center, 6);
mgr = new GMarkerManager(map,{maxZoom: 19});
refreshMarkers();
}
}
function refreshMarkers()
{
clearTimeout(timeOut);
GDownloadUrl('dane2.php', function(dane,respCode)
{
if(respCode==200)
{
var xml = GXml.parse(dane);
var marker = dodajMarker(arguments, 15, 15);
}
else
{
alert('Cant open dane2.php');
}
});
mgr.clearMarkers(); // ???
timeOut=setInterval("refreshMarkers()",2000);
}
function dodajMarker(arguments, minZoom, maxZoom)
{
var ikona = new GIcon();
ikona.image = 'http://www.google.com/intl/en_ALL/mapfiles/dd-start.png';
ikona.iconSize = new GSize(20, 34);
ikona.iconAnchor = new GPoint(10, 34);
var marker = new GMarker(new GLatLng(latitude,longitude),{icon: ikona});
mgr.addMarker(marker,minZoom,maxZoom);
return marker;
}
</script>
<div id="map" style="align: center; width: 1000px; height: 490px; solid black; background: gray;"></div>
</body>
</html>
My page: http://m2mgsm.com/gps/index.php You can login: "admin", password: "12345" Click Test Map ("Mapatesty" - polish language only, english soon) in menu and then Select IMEI ("Wybierz IMEI") e.g. 355832010123229 and check Route ("Pokaż trasę:") and From/To ("Od/Do") date (e.g. 05.01.2012/05.01.2012) and "Filtruj". You can now view source of my map script in frame. I want to refresh ONLY markers with e.g. 3 sec. interval and it works, but new markers are OVERLAY on old markers...
Ps. Sorry for my English.
You have errors is your JS:
ReferenceError: kontener is not defined [http://m2mgsm.com/gps/mapatesty.php:259]
TypeError: Object #<yv> has no method 'clearMarkers' [http://m2mgsm.com/gps/mapatesty.php:459]
Try to use Firefox with Firebug extension or Chrome with its built-in Debugger to trace through your JavaScript code and eliminate the bugs.