Work with advanced layer types including WMS, WFS, WMTS, OGCFeatureLayer, MapImageLayer, CatalogLayer, MediaLayer, and dynamic data layers. Use for OGC services, server-side rendering, and georeferenced media content.
59
68%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Fix and improve this skill with Tessl
tessl review fix ./contexts/4.34/skills/arcgis-advanced-layers/SKILL.mdUse this skill for working with OGC services, MapImageLayer, CatalogLayer, MediaLayer, and dynamic data layers.
import WMSLayer from "@arcgis/core/layers/WMSLayer.js";
const layer = new WMSLayer({
url: "https://ows.terrestris.de/osm/service"
});
await layer.load();
// Find and use a specific sublayer
const sublayer = layer.findSublayerByName("OSM-WMS");
if (sublayer) {
layer.sublayers = [sublayer];
}
map.add(layer);<arcgis-scene>
<arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-scene>
<script type="module">
import WMSLayer from "@arcgis/core/layers/WMSLayer.js";
const viewElement = document.querySelector("arcgis-scene");
const layer = new WMSLayer({
url: "https://ows.terrestris.de/osm/service"
});
await layer.load();
const sublayer = layer.findSublayerByName("OSM-WMS");
if (sublayer) {
layer.sublayers = [sublayer];
}
viewElement.map = {
basemap: {
baseLayers: [layer],
title: "WMS Layer"
}
};
</script>import WFSLayer from "@arcgis/core/layers/WFSLayer.js";
const layer = new WFSLayer({
url: "https://geobretagne.fr/geoserver/ows",
name: "fma:bvme_zhp_vs_culture",
copyright: "GéoBretagne"
});
map.add(layer);import WFSLayer from "@arcgis/core/layers/WFSLayer.js";
import wfsUtils from "@arcgis/core/layers/ogc/wfsUtils.js";
// Get capabilities from WFS endpoint
const capabilities = await wfsUtils.getCapabilities("https://geobretagne.fr/geoserver/ows");
// List available feature types
capabilities.featureTypes.forEach(featureType => {
console.log(featureType.title, featureType.name);
});
// Create layer from specific feature type
const layerInfo = await wfsUtils.getWFSLayerInfo(capabilities, "featureTypeName");
const layer = WFSLayer.fromWFSLayerInfo(layerInfo);
map.add(layer);import WMTSLayer from "@arcgis/core/layers/WMTSLayer.js";
const layer = new WMTSLayer({
url: "https://www.ign.es/wmts/ign-base",
activeLayer: {
id: "IGNBase-gris",
tileMatrixSetId: "GoogleMapsCompatible"
},
serviceMode: "KVP",
copyright: "Instituto Geográfico Nacional"
});
map.add(layer);import Basemap from "@arcgis/core/Basemap.js";
import WMTSLayer from "@arcgis/core/layers/WMTSLayer.js";
const wmtsBasemap = new Basemap({
baseLayers: [
new WMTSLayer({
url: "https://www.ign.es/wmts/ign-base",
activeLayer: { id: "IGNBase-gris", tileMatrixSetId: "GoogleMapsCompatible" },
serviceMode: "KVP"
})
],
thumbnailUrl: "https://example.com/thumbnail.jpg"
});
const map = new Map({
basemap: wmtsBasemap
});import OGCFeatureLayer from "@arcgis/core/layers/OGCFeatureLayer.js";
const layer = new OGCFeatureLayer({
url: "https://demo.ldproxy.net/vineyards", // OGC API landing page
collectionId: "vineyards", // Collection ID
minScale: 5000000,
renderer: {
type: "simple",
symbol: {
type: "simple-fill",
color: [76, 129, 64, 0.6]
}
},
popupTemplate: {
title: "{name}",
content: "Area: {area_ha} hectares"
}
});
map.add(layer);const layer = new OGCFeatureLayer({
url: "https://demo.ldproxy.net/vineyards",
collectionId: "vineyards",
labelingInfo: [{
labelExpressionInfo: {
expression: "$feature.NAME"
},
symbol: {
type: "text",
color: "#4a6741",
haloSize: 1,
haloColor: "white",
font: {
family: "Arial",
style: "italic"
}
},
minScale: 100000
}]
});import MapImageLayer from "@arcgis/core/layers/MapImageLayer.js";
// From portal item
const layer = new MapImageLayer({
portalItem: {
id: "d7892b3c13b44391992ecd42bfa92d01"
}
});
// From URL
const layer2 = new MapImageLayer({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer"
});
map.add(layer);const layer = new MapImageLayer({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer",
sublayers: [
{ id: 2, visible: true }, // States
{ id: 1, visible: true }, // Highways
{ id: 0, visible: true } // Cities
]
});
// Toggle sublayer visibility
layer.when(() => {
const sublayer = layer.findSublayerById(1);
sublayer.visible = !sublayer.visible;
});const layer = new MapImageLayer({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer",
sublayers: [{
id: 0,
definitionExpression: "pop2000 > 100000"
}]
});const layer = new MapImageLayer({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer",
sublayers: [{
id: 2,
renderer: {
type: "simple",
symbol: {
type: "simple-fill",
color: [0, 100, 200, 0.5],
outline: { color: "white", width: 1 }
}
}
}]
});const layer = new MapImageLayer({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/USA/MapServer",
sublayers: [{
id: 4,
title: "Railroads",
renderer: {
type: "simple",
symbol: {
type: "simple-line",
color: [255, 255, 255, 0.5],
width: 0.75,
style: "long-dash-dot-dot"
}
},
source: {
type: "data-layer",
dataSource: {
type: "table",
workspaceId: "MyDatabaseWorkspaceIDSSR2",
dataSourceName: "ss6.gdb.Railroads"
}
}
}]
});const layer = new MapImageLayer({
url: "https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer",
sublayers: [{
id: 0,
opacity: 0.75,
source: {
type: "data-layer",
dataSource: {
type: "join-table",
// Left table: map layer with geometries
leftTableSource: {
type: "map-layer",
mapLayerId: 3
},
// Right table: data table in workspace
rightTableSource: {
type: "data-layer",
dataSource: {
type: "table",
workspaceId: "CensusFileGDBWorkspaceID",
dataSourceName: "ancestry"
}
},
leftTableKey: "STATE_NAME",
rightTableKey: "State",
joinType: "left-outer-join"
}
},
renderer: {
type: "class-breaks",
field: "ancestry.Norwegian",
normalizationField: "states.POP2007",
classBreakInfos: [
{ minValue: 0, maxValue: 0.01, symbol: createSymbol("#f8e3c2") },
{ minValue: 0.01, maxValue: 0.05, symbol: createSymbol("#d86868") }
]
}
}]
});import CatalogLayer from "@arcgis/core/layers/CatalogLayer.js";
const layer = new CatalogLayer({
portalItem: {
id: "487cc66d305145d3b67fed383456af48",
portal: {
url: "https://jsapi.maps.arcgis.com/"
}
}
});
map.add(layer);import CatalogLayer from "@arcgis/core/layers/CatalogLayer.js";
import catalogUtils from "@arcgis/core/layers/catalog/catalogUtils.js";
const layer = new CatalogLayer({
portalItem: { id: "YOUR_CATALOG_ITEM_ID" }
});
map.add(layer);
const layerView = await view.whenLayerView(layer);
// Query all footprints
const result = await layer.queryFeatures({
where: "1=1",
returnGeometry: true,
outFields: ["*"],
orderByFields: [layer.itemNameField]
});
// Add labels to footprint layer
layer.footprintLayer.labelingInfo = [{
labelExpressionInfo: {
expression: "$feature." + layer.itemNameField
},
symbol: {
type: "label-3d",
symbolLayers: [{
type: "text",
material: { color: "white" },
size: 10
}]
}
}];
// Highlight a footprint
const highlight = layerView.footprintLayerView.highlight(feature);
// Create layer from footprint
const footprint = layer.createFootprintFromLayer(selectedLayer);
const newLayer = await layer.createLayerFromFootprint(footprint);
map.add(newLayer);const layerList = document.querySelector("arcgis-layer-list");
layerList.catalogOptions = {
selectionMode: "single"
};
layerList.listItemCreatedFunction = (event) => {
if (catalogUtils.isLayerFromCatalog(event.item.layer)) {
event.item.actionsSections = [[{
title: "Add layer to map",
icon: "add-layer",
id: "add-layer"
}]];
}
};import MediaLayer from "@arcgis/core/layers/MediaLayer.js";
import ImageElement from "@arcgis/core/layers/support/ImageElement.js";
import ExtentAndRotationGeoreference from "@arcgis/core/layers/support/ExtentAndRotationGeoreference.js";
import Extent from "@arcgis/core/geometry/Extent.js";
const imageElement = new ImageElement({
image: "https://example.com/historical-map.png",
georeference: new ExtentAndRotationGeoreference({
extent: new Extent({
xmin: -10047456,
ymin: 3486722,
xmax: -10006982,
ymax: 3514468,
spatialReference: { wkid: 102100 }
})
})
});
const mediaLayer = new MediaLayer({
source: [imageElement],
title: "Historical Map"
});
map.add(mediaLayer);const imageInfos = [
{
url: "image1.png",
extent: { xmin: -100, ymin: 30, xmax: -90, ymax: 40 }
},
{
url: "image2.png",
extent: { xmin: -95, ymin: 35, xmax: -85, ymax: 45 }
}
];
const imageElements = imageInfos.map(info => new ImageElement({
image: info.url,
georeference: new ExtentAndRotationGeoreference({
extent: new Extent({
...info.extent,
spatialReference: { wkid: 4326 }
})
})
}));
const mediaLayer = new MediaLayer({
source: imageElements
});const georeference = new ExtentAndRotationGeoreference({
extent: new Extent({
xmin: -122.5,
ymin: 37.5,
xmax: -122.0,
ymax: 38.0,
spatialReference: { wkid: 4326 }
}),
rotation: 15 // Degrees clockwise
});import ControlPointsGeoreference from "@arcgis/core/layers/support/ControlPointsGeoreference.js";
const georeference = new ControlPointsGeoreference({
controlPoints: [
{
sourcePoint: { x: 0, y: 0 }, // Top-left of image (pixels)
mapPoint: { x: -122.5, y: 38.0 } // Map coordinates
},
{
sourcePoint: { x: 1000, y: 0 }, // Top-right
mapPoint: { x: -122.0, y: 38.0 }
},
{
sourcePoint: { x: 1000, y: 800 }, // Bottom-right
mapPoint: { x: -122.0, y: 37.5 }
},
{
sourcePoint: { x: 0, y: 800 }, // Bottom-left
mapPoint: { x: -122.5, y: 37.5 }
}
],
width: 1000, // Image width in pixels
height: 800 // Image height in pixels
});import VideoElement from "@arcgis/core/layers/support/VideoElement.js";
const videoElement = new VideoElement({
video: "https://example.com/timelapse.mp4",
georeference: new ExtentAndRotationGeoreference({
extent: new Extent({
xmin: -122.5,
ymin: 37.5,
xmax: -122.0,
ymax: 38.0,
spatialReference: { wkid: 4326 }
})
})
});
const mediaLayer = new MediaLayer({
source: [videoElement]
});
// Control video playback
videoElement.content.play();
videoElement.content.pause();
videoElement.content.currentTime = 30; // Seek to 30 seconds// Animated GIFs work like regular images
const gifElement = new ImageElement({
image: "https://example.com/weather-animation.gif",
georeference: new ExtentAndRotationGeoreference({
extent: new Extent({
xmin: -130,
ymin: 25,
xmax: -65,
ymax: 50,
spatialReference: { wkid: 4326 }
})
})
});
const mediaLayer = new MediaLayer({
source: [gifElement]
});const mediaLayer = new MediaLayer({
source: [imageElement],
opacity: 0.7,
blendMode: "multiply" // normal, multiply, luminosity, etc.
});
// Change opacity dynamically
mediaLayer.opacity = 0.5;
// Change blend mode
mediaLayer.blendMode = "luminosity";// Individual element opacity
imageElement.opacity = 0.8;
// Update dynamically
document.getElementById("opacitySlider").addEventListener("input", (e) => {
imageElement.opacity = e.target.value / 100;
});// Access source
const source = mediaLayer.source;
// Add elements
source.elements.push(newImageElement);
source.elements.push(element1, element2);
// Remove elements
source.elements.splice(source.elements.indexOf(imageElement), 1);
source.elements.length = 0; // Remove all
// Iterate elements
source.elements.forEach(element => {
console.log(element.image || element.video);
});// Enable interactive editing of georeference control points
const mediaLayerView = await view.whenLayerView(mediaLayer);
// Enable interactive mode to allow control point editing
mediaLayerView.interactive = true;
// Disable interactive mode
mediaLayerView.interactive = false;<arcgis-map center="-89.93, 29.97" zoom="10">
<arcgis-zoom slot="top-left"></arcgis-zoom>
</arcgis-map>
<script type="module">
import MediaLayer from "@arcgis/core/layers/MediaLayer.js";
import ImageElement from "@arcgis/core/layers/support/ImageElement.js";
import ExtentAndRotationGeoreference from "@arcgis/core/layers/support/ExtentAndRotationGeoreference.js";
import Extent from "@arcgis/core/geometry/Extent.js";
import Map from "@arcgis/core/Map.js";
const viewElement = document.querySelector("arcgis-map");
// Create image elements for historical maps
const imageElements = [
{
name: "1891 Map",
url: "https://example.com/map-1891.png",
extent: { xmin: -10047456, ymin: 3486722, xmax: -10006982, ymax: 3514468 }
},
{
name: "1920 Map",
url: "https://example.com/map-1920.png",
extent: { xmin: -10045000, ymin: 3488000, xmax: -10008000, ymax: 3516000 }
}
].map(info => new ImageElement({
image: info.url,
georeference: new ExtentAndRotationGeoreference({
extent: new Extent({
...info.extent,
spatialReference: { wkid: 102100 }
})
})
}));
const mediaLayer = new MediaLayer({
source: imageElements,
title: "Historical Maps",
blendMode: "normal"
});
viewElement.map = new Map({
basemap: "topo-vector",
layers: [mediaLayer]
});
</script>| Layer Type | Use Case | Data Source |
|---|---|---|
| WMSLayer | Raster imagery from OGC WMS | WMS 1.1.1/1.3.0 |
| WFSLayer | Vector features from OGC WFS | WFS 2.0.0 |
| WMTSLayer | Cached tiles from OGC WMTS | WMTS 1.0.0 |
| OGCFeatureLayer | Vector from OGC API - Features | OGC API |
| MapImageLayer | Server-rendered imagery | ArcGIS Map Service |
| CatalogLayer | Collection of layers | ArcGIS Catalog Service |
| MediaLayer | Georeferenced images, video, GIFs | Local/remote media |
layers-wms - Adding and configuring WMS layerslayers-wfs - Working with WFS layerslayers-ogcfeaturelayer - OGC Features API layer usagelayers-mapimagelayer - Dynamic MapImageLayer configurationlayers-cataloglayer - Using CatalogLayer to browse portal contentlayers-medialayer-images - Displaying images with MediaLayerlayers-medialayer-video - Video playback in MediaLayerlayers-medialayer-control-points - Control point placement for medialayers-medialayer-interactive - Interactive media layer manipulationWFS version: WFSLayer requires WFS 2.0.0 with GeoJSON output format
CORS: OGC services need CORS headers or proxy configuration
Sublayer IDs: MapImageLayer sublayer IDs must match service layer IDs
Dynamic data sources: Require registered workspaces on the server
CatalogLayer portal: Must specify portal URL for non-ArcGIS Online items
Field prefixes: In joined tables, prefix field names with table name (e.g., ancestry.Norwegian)
Media CORS: Images and videos from external servers need CORS headers
Video autoplay: Browsers may block autoplay - require user interaction first
d84407b
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.