POST
|
This is my workaround for replacing default feature symbols with custom (non ArcGIS server-side) symbols when dealing with a dynamic map service layer. It's true, you cannot apply SVG paths unless it's a client side graphic. However, it may not be desirable to introduce a separate graphic layer if you just need to directly re-symbolize a dynamic layer's features. The best alternative I see is to create a custom png or jpg and then convert the image into base 64 data URI format. There are free online tools available for generating the portion needed for the "imageData" parameter. var imgDataGreenValveIcon = "iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAACNiR0NAAAACXBIWXMAAA7EAAAOxAGVKw4bAAAAB3RJTUUH4AkNDjYKRr1e7wAAAJBJREFUOMtjYBgFVAdODY7/KVHLhFthHhs5FjPh1nD5J4NDqQCpvmDC6wqHM+/RNRMKEiZiwso007eW2PAlykBe8S9NxEYWE7VTCdEG7jtgIkg1A/c17GdkOND9YV+DBTdFBn56ztewr2E/I0Kk/du+Bgs2sg08M3NjI6Zo++99DfuZSct6toWC1M6mo4B4AABZQDTkVUGpogAAAABJRU5ErkJggg==";
var picSymbol = new PictureMarkerSymbol({
"type": "esriPMS",
"imageData": imgDataGreenValveIcon,
"contentType": "image/png",
"width": 20,
"height": 20
});
... View more
09-13-2016
08:24 AM
|
0
|
0
|
781
|
POST
|
Can a SimpleMarkerSymbol, created from an SVG path, be used as a renderer in LayerDrawingOptions for DynamicMapServiceLayers? See my example below. I don't get any errors. It simply doesn't show the SVG (red triangle) symbol for the fire station layer features - layer 7. The same SVG symbol displays fine if I apply it to a graphic and add the graphic to the map, but nothing appears when applied to a dynamic map service layer. My ultimate goal is to use custom SVG path text (e.g. "M100, 100......") with UniqueValueRenderer symbols. <!DOCTYPE html>
<html>
<head>
<title>SVG render test</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
<link rel="stylesheet" href="https://js.arcgis.com/3.17/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.17/dojox/widget/ColorPicker/ColorPicker.css">
<link rel="stylesheet" href="https://js.arcgis.com/3.17/esri/css/esri.css">
<style>
html, body, #map {
height:100%;
width:100%;
margin:0;
padding:0;
}
</style>
<script src="https://js.arcgis.com/3.17/"></script>
<script>
require([
"esri/map", "esri/geometry/Point",
"esri/graphic", "esri/SpatialReference", "esri/geometry/Extent",
"esri/Color", "esri/layers/ArcGISDynamicMapServiceLayer",
"esri/symbols/SimpleLineSymbol", "esri/symbols/SimpleMarkerSymbol", "esri/symbols/SimpleFillSymbol",
"esri/renderers/SimpleRenderer", "esri/layers/LayerDrawingOptions", "esri/config",
"dojo/_base/array", "dojo/dom-style",
"dojo/domReady!"
], function(
Map, Point,
Graphic, SpatialReference, Extent,
Color, ArcGISDynamicMapServiceLayer,
SimpleLineSymbol, SimpleMarkerSymbol, SimpleFillSymbol,
SimpleRenderer, LayerDrawingOptions, esriConfig,
arrayUtils, domStyle
) {
var app = {};
app.defaultExtent = new Extent(-97.78219462135767, 30.25811946558375, -97.6972260613063, 30.30040143951408,
new SpatialReference({ wkid: 4326 })
);
app.map = new Map("map", {
extent: app.defaultExtent,
sliderPosition: "bottom-left",
sliderStyle: "small"
});
app.layerTestURL = "http://services.nationalmap.gov/arcgis/rest/services/structures/MapServer";
app.layerTest = new ArcGISDynamicMapServiceLayer(app.layerTestURL);
app.map.addLayer(app.layerTest);
app.layerTest.on("load", function (e) {
resymbolizeTestLayer();
});
function resymbolizeTestLayer() {
var iconPath = "M100,100 L300,100 L200,300 Z";
var markerSymbol = new SimpleMarkerSymbol();
markerSymbol.setPath(iconPath);
markerSymbol.setColor(new Color([220, 10, 20, 1]));
markerSymbol.setOutline(null);
var layerDrawingOptions = [];
var drawOpt = new LayerDrawingOptions();
drawOpt.renderer = new SimpleRenderer(markerSymbol);
layerDrawingOptions[7] = drawOpt;
app.layerTest.setLayerDrawingOptions(layerDrawingOptions);
}
});
</script>
</head>
<body class="claro">
<div id="map"></div>
</body>
</html>
... View more
09-07-2016
01:45 PM
|
0
|
2
|
1914
|
POST
|
The encoding addition doesn't fix it for me. I'm also using latest DotNet proxy (1.1.0), along with IE 11 + JS API 3.17 + ArcGIS 10.22. The cancel error is caused by either of the following, specifically due to interrupting the map redrawing, as the response url points to the "export" task ( "/...proxy.ashx?http://myserver.domain/..../MapServer/export?") 1) Using LayerDrawingOptions on a dynamic map service to render a layer with a custom symbol drawingOptions.renderer = new SimpleRenderer(polygonSymbol);
optionsArray[0] = drawingOptions;
app.myMapServiceLayer.setLayerDrawingOptions(optionsArray); 2) Using LayerDrawingOptions with LabelClass on multiple layers within a dynamic map service var drawingOptionsLabelClass = new LayerDrawingOptions();
var labelClass = new LabelClass({
labelExpression: '[my_field_name]',
labelPlacement: 'above-center',
symbol: labelSymbol
});
drawingOptionsLabelClass.labelingInfo = [labelClass];
drawingOptionsLabelClass.showLabels = true;
optionsArray[1] = drawingOptionsLabelClass;
optionsArray[2] = drawingOptionsLabelClass;
app.SomeOtherMapServiceLayer.setLayerDrawingOptions(optionsArray); No cancel errors are displayed when only applying LabelClass against one layer. Not expecting help, just thought I'd point this out. There may be no way to eliminate the console message because I suspect it's a case where the ESRI JS API's deferreds are being cancelled and "cancel error" is the generic catch all message. From DoJo documentation: dojo/errors/CancelError is the default error if a promise is canceled without a reason
... View more
07-01-2016
08:01 AM
|
0
|
0
|
914
|
POST
|
Brilliant. Thank you for sharing, Brendan! I replaced my code to use the LabelClass with halos. It now includes labels and a background when exporting to PDF using PrintTask, unlike LabelLayer class method (per my previous post above). Works for IE 10 and 11.0.96.
... View more
12-04-2015
08:37 AM
|
0
|
2
|
684
|
POST
|
Similar to Rahul Metangale's post above, I found SVG rectangles to be the best approach. This works well to remove & re-create the label background each time the map is redrawn (after pan or zoom). function turnOnLabels() {
var labelLayerNode = labelLyr.getNode();
if (!labelLayerNode || labelLayerNode === null) {
return;
}
var textLabels = query("text", labelLayerNode);
array.forEach(textLabels, function (label) {
var txtContent = label.textContent;
label.textContent = txtContent.replace("null", "");
var lBox = label.getBBox();
label.innerHTML = label.textContent
var rect = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
rect.setAttribute("x", lBox.x);
rect.setAttribute("y", lBox.y);
rect.setAttribute("width", lBox.width + 1); //added a little margin
rect.setAttribute("height", lBox.height - 2); //trimmed down margin
rect.setAttribute("fill", "rgba(255,255,255,0.9)"); //opacity of 0.9 can be adjusted
labelLayerNode.insertBefore(rect, label);
});
}
function turnOffLabels() {
var labelLayerNode = labelLyr.getNode();
if (!labelLayerNode) { return; }
var elements = labelLayerNode.querySelectorAll("rect");
for (var i = 0; i < elements.length; ++i) {
var elem = elements;
labelLayerNode.removeChild(elem);
}
}
app.map.on('update-start', function () {
turnOffLabels();
});
app.map.on('update-end', function () {
turnOnLabels();
}); Edit: It works well enough for visual display on the screen, but I discovered these svg rectangles are lost when I export to PDF using PrintTask (esri/tasks/PrintTask). I am going to contact ESRI about this, but I would be interested in knowing if there is any workaround. Here is a JSFiddle example to illustrate the problem: http://jsfiddle.net/r2nnrL3t Edit #2: I confirmed with ESRI support services this is a known issue: The bug id is NIM090851 : Export Web Map Task cannot print a map using SVG symbol types in JavaScript API 3.4. The status of the bug is set to "Tech review Complete" which means that the bug has been reviewed by the Technical Leads and now it's being reviewed by the Product Engineers, and then it will be assigned to the development team for a fix. Therefore, my solution is to use LabelClass with halo color and halo size properties (Brendan Madden's solution below). It is compatible with PrintTask and gets the job done to provide a background for contrast.
... View more
10-08-2015
07:05 AM
|
0
|
0
|
684
|
POST
|
Apparently all I needed to do was remove the "$" in the text expression "${" + labelField + "}". It now shows the Description value if the field is associated with a domain, or else the value if it is plain text, number, date, etc. labels.addFeatureLayer(wlFeatLayer, labelRenderer, "{" + labelField + "}"); You might say removing the dollar sign was right on the money! hah
... View more
04-23-2015
02:28 PM
|
1
|
0
|
256
|
POST
|
My goal: Allow users to dynamically add labels. They would select a field to be labeled along with their preferred font size and color. LabelLayer appears to be the closest solution. My code below is working without error, however it shows the domain Coded Values instead of the readable Description values. Is there any workaround to get the description text whenever the field is associated with a domain? Here is an example of converting a domain value's code to description Using Domain values in your App But this doesn't help because LabelLayer's ".addFeatureLayer" method doesn't appear to allow anything more than the field name itself. function addLabelLayer() {
var labelField = "SOURCE";
var colorLabel = new Color("#0000FF");
var labelTextSymbol = new TextSymbol().setColor(colorLabel);
labelTextSymbol.font.setSize("12pt");
labelTextSymbol.font.setFamily("arial");
var labelRenderer = new SimpleRenderer(labelTextSymbol);
var wlFeatLayer = new FeatureLayer(
mapServerURL + "/15",
{
id: "wlFeatureLayer",
outFields: ["*"]
});
wlFeatLayer.on('load', function () {
var labels = new LabelLayer({ id: "wlLabels" });
labels.addFeatureLayer(wlFeatLayer, labelRenderer, "${" + labelField + "}");
app.map.addLayer(labels);
labels.visible = true;
});
app.map.addLayer(wlFeatLayer);
}
... View more
04-23-2015
01:03 PM
|
0
|
1
|
2831
|
POST
|
Terese Rowekamp wrote: Here's the result: 1. Open ArcMap and show toolbar - all buttons are visible. 2. Leave toolbar open, close ArcMap, open ArcMap - buttons are hidden. 3. Close toolbar, close ArcMap - back to behavior number 1. So, as long as ArcMap is closed with the toolbar visible, the buttons are hidden when ArcMap is re-opened. Whenever the toolbar needs to be opened by the user, the buttons are not hidden. I am stuck here, too. Exact same issue, I want to keep a button fully hidden (not disabled) in a toolbar if the user is part of a specific Active Directory group. The problem is that there is no event exposed in the Add-in ArcObjects API for when you make the toolbar visible if it wasn't already visible when opening ArcMap. I would greatly appreciate any workarounds!
... View more
03-24-2015
09:07 AM
|
0
|
0
|
169
|
POST
|
Update: I found a solution. It was hard to reproduce this issue with any other 10.02 map service / JS API 3.10 combination. However, I used LAYER_OPTION_ALL combined with this function below to guarantee I will only identify against currently visible layers at the current map scale. The scale range was the key here.
function visibleAtCurExtent(layerInfo) {
isVisible = false;
//First criteria: must be a layer that is checked as visible; this doesn't guarantee it's visible at the current map extent
if (array.indexOf(serviceLayer.visibleLayers, layerInfo.id) > -1) {
var mapScale = map.getScale(); // initial: 288,000
var layerMinScale = layerInfo.minScale; //fittings: min=1000, max=0
var layerMaxScale = layerInfo.maxScale;
//If layer has no min/max scale range, or currently above min scale range and no max scale or below max scale range, it is visible
if ((layerMinScale === 0 && layerMaxScale === 0) || (layerMinScale >= mapScale && (layerMaxScale === 0 || layerMaxScale <= mapScale))) {
isVisible = true;
}
}
return isVisible;
}
Then, apply when looping through DynamicLayerInfos: array.forEach(dynamicLayerInfos, function (info) {
var blnVisAtCurExt = visibleAtCurExtent(info);
......
... View more
01-20-2015
01:47 PM
|
0
|
0
|
227
|
POST
|
Ken, thanks for confirming this scenario. I happen to have a virtual server with 10.2.0 services running, and after substituting with a similar map service (also containing subgroups) it does indeed return the sublayers. May I ask what API and Server combination you are using? Just for additional reference. Much appreciated!
... View more
12-04-2014
03:03 PM
|
0
|
0
|
1776
|
POST
|
My application loads multiple map services, and within two of the services there are grouped layers (created in ArcMap). Is it possible to return identify results for sublayers under a grouped layer, when not visible by default? For example see below, or image attached: Water Layers (= map service level) - Water Valve - Water Fire Hydrant - Water Abandoned/Removed (= layer group, not visible by defaul) - Fire Hydrant (A/R) - Water Valve (A/R) - Water Line (A/R) - Water Line Using the "LAYER_OPTION_VISIBLE" layerOption doesn't work. The "Water Abandoned/Removed" group layer is not visible by default from the mxd settings, so users must make it visible by checking it on the TOC/Legend (widget by NLiu). With this group layer and all sublayers checked, and when zoomed to a visible scale range, no results are found. I tried applying your code above with no success either. My identify code is rather long, as I built a custom info window, but here's where I set the currently visible layers upon map "click" event. It passes the correct ID's into the array [8,9,10] which equate to Fire Hydrant (A/R), Water Valve (A/R), and Water Line (A/R). But Identify Task does not produce any results for these three layers. It only works if I use LAYER_OPTION_ALL, but then I have the obvious problem of returning results from layers not currently visible. function buildCurrentMapServiceLayerList(serviceLayer) {
var lyrInfos = {};
var hasVisibleLayers = false;
dynamicLayerInfos = serviceLayer.createDynamicLayerInfosFromLayerInfos();
array.forEach(dynamicLayerInfos, function (info) {
var i = {
id: info.id,
name: info.name
};
if (array.indexOf(serviceLayer.visibleLayers, info.id) > -1) {
i.visible = true;
hasVisibleLayers = true;
}
else {
i.visible = false;
}
if (!info.subLayerIds) {
lyrInfos[info.id] = i;
}
});
if (hasVisibleLayers === true) {
mapServiceInfos[serviceLayer.id] = lyrInfos;
}
} Then, to create parameters and execute identify task... var serviceName = mapServiceInfos[idxName];
for (var idxLayer in serviceName) { //loop through layers within the current map service
var layer = serviceName[idxLayer];
if (layer.name.toUpperCase().indexOf("LABEL") == -1 && layer.visible == true) {
layersToIdentify.push(layer.id);
}
}
identifyParams.layerIds = layersToIdentify;
identifyParams.tolerance = 8;
identifyParams.returnGeometry = true;
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE;
identifyParams.width = map.width;
identifyParams.height = map.height;
identifyParams.geometry = event.mapPoint;
identifyParams.mapExtent = map.extent;
if (layersToIdentify.length > 0) {
var idDeferred = identifyTask.execute(identifyParams, function (idResults) {
processIdentifyResults(idResults, event);
});
} (Using js api 3.10 against ArcGIS Server 10.0 services, soon to upgrade to 10.2.2)
... View more
12-04-2014
02:01 PM
|
0
|
1
|
3147
|
POST
|
I have no problem with identifying multiple map services, but within two of the services there are grouped layers. I cannot get results returned for sublayers. For example see below, or image attached: Water Layers (= map service level) - Water Valve - Water Fire Hydrant - Water Abandoned/Removed (= layer group, not visible by default) - Fire Hydrant (A/R) - Water Valve (A/R) - Water Line (A/R) - Water Line Using the "LAYER_OPTION_VISIBLE" layerOption doesn't work. The "Water Abandoned/Removed" group layer is not visible by default from the mxd settings, so users must make it visible by checking it on the TOC/Legend (widget by NLiu). With the group layer and all sublayers checked, and within the visible scale range, nothing is returned in results. I tried applying your code above with no success either. My identify code is rather long, as I built a custom info window, but here's where I set the currently visible layers upon map "click" event. It passes the correct ID's into the array [8,9,10] which equate to Fire Hydrant (A/R), Water Valve (A/R), and Water Line (A/R). But Identify Task does not produce any results for these three layers. It only works if I use LAYER_OPTION_ALL, but then I have the obvious problem of returning results from layers not currently visible. function buildCurrentMapServiceLayerList(serviceLayer) {
var lyrInfos = {};
var hasVisibleLayers = false;
dynamicLayerInfos = serviceLayer.createDynamicLayerInfosFromLayerInfos();
array.forEach(dynamicLayerInfos, function (info) {
var i = {
id: info.id,
name: info.name
};
if (array.indexOf(serviceLayer.visibleLayers, info.id) > -1) {
i.visible = true;
hasVisibleLayers = true;
}
else {
i.visible = false;
}
if (!info.subLayerIds) {
lyrInfos[info.id] = i;
}
});
if (hasVisibleLayers === true) {
mapServiceInfos[serviceLayer.id] = lyrInfos;
}
} Then, to create parameters and execute identify task... var serviceName = mapServiceInfos[idxName];
for (var idxLayer in serviceName) { //loop through layers within the current map service
var layer = serviceName[idxLayer];
if (layer.name.toUpperCase().indexOf("LABEL") == -1 && layer.visible == true) {
layersToIdentify.push(layer.id);
}
}
identifyParams.layerIds = layersToIdentify;
identifyParams.tolerance = 8;
identifyParams.returnGeometry = true;
identifyParams.layerOption = IdentifyParameters.LAYER_OPTION_VISIBLE;
identifyParams.width = map.width;
identifyParams.height = map.height;
identifyParams.geometry = event.mapPoint;
identifyParams.mapExtent = map.extent;
if (layersToIdentify.length > 0) {
var idDeferred = identifyTask.execute(identifyParams, function (idResults) {
processIdentifyResults(idResults, event);
});
} (Using js api 3.10 against ArcGIS Server 10.0 services, soon to upgrade to 10.2.2)
... View more
12-04-2014
01:02 PM
|
0
|
3
|
1776
|
POST
|
I'm working on an evaluation of the Data Reviewer extension for our organization, and after walking through a few examples of running checks and batch jobs I'm curious to know the limits of the Reviewer table. I see how you can push the results of your batch job(s) into it, and then how you can manually step through each record to fix the problem (and update the correction/verification status) and/or just delete the record. Perhaps I missed something under the Help section, but I don't see an obvious way to re-run batch job(s) and have it remove any of the errors that have now been corrected in your GIS data. In other words, an automated removal of the Reviewer record because it doesn't apply anymore as an error. (example: my first run produces REVIEWSTATUS = "Material: Invalid domain value", so after fixing the record's "Material" field value in the feature class I re-run the batch job and this Reviewer table record no longer exists) Is the only way to remove it by either selecting and pressing Delete, or else some sort of Python geo-processing script?
... View more
07-09-2013
10:25 AM
|
1
|
2
|
3519
|
Title | Kudos | Posted |
---|---|---|
1 | 04-23-2015 02:28 PM | |
1 | 07-09-2013 10:25 AM |
Online Status |
Offline
|
Date Last Visited |
11-11-2020
02:23 AM
|