How do I retrieve the color of a simple line symbol from specific layers in a web map?
I'm using an existing web map and want to create my own symbols for 3 of the layers in the map. I am able to create the full legend via the sample but I'm struggling to simply grab colors. In the image below, the full legend created from the LegendInfoListModel is at the bottom in the tab but I need to color the rectangles at the top according to the legend info (hard coded now). I am a web developer so perhaps am missing a pattern here. Any help?
Solved! Go to Solution.
@DavidPuckett interesting, yes could be something with the data. I am getting the name printed out, but it does depend on which legendInfo it is, and it will also depend on the source data online and whether that contains any name info.
Row {
Component.onCompleted: {
if (index !== -1) {
let legendInfo = map.legendInfos.get(index);
console.log(legendInfo.name);
}
}
Using that with the sample prints as follows as I scroll through the legend:
qml: 0 - 61
qml: 62 - 264
qml: 265 - 759
qml: 760 - 1900
qml: 1901 - 9409
qml:
qml:
qml:
qml: Camping
qml: Dining
qml: Drinking Water
qml: Medical Facility
You can see that some of the legend entries here don't contain any "label"
https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/legend?f=pjson
Hi David.
If you have the legend info, you should have access to the symbol.
How you get the color out of that symbol will depend on the type of symbol and how the web map was authored, but explore the various symbol types (SimpleLineSymbol, CompositeSymbol, MultilayerPolylineSymbol) which should eventually lead you to a color.
Hope that helps.
Thanks for this Nick, I should have provided more detail however. I am having 2 issues that are keeping me from applying colors dynamically:
For now I am using the operationalLayers to get the color for specific layers via the renderer like so:
operationalLayers.forEach(layer =>
{
// only way i can see to identify layers is by name, brittle but...
if(layer.name === "Serviced 3+ Hours Ago") {
servicedRoute3PlusHoursLayerLegendColor = layer.renderer.symbol.color;
}
else if(layer.name === "Serviced 1-3 Hours Ago") {
servicedRoute1To3HoursLayerLegendColor = layer.renderer.symbol.color;
}
else if(layer.name === "Serviced Less Than 1 Hour Ago") {
servicedRoute1HourLayerLegendColor = layer.renderer.symbol.color;
}
else if(layer.name === "Closed Road") {
closedRoadLayerLegendColor = layer.renderer.symbol.color;
}
})
I am certainly open to using legendInfos if these issues can be resolved and share with the community here.
Hi @DavidPuckett,
Looks like you're on the right track. Take a look at our QML BuildLegend sample for some guidance.
A few things you want to check for are to be sure that the autoFetchLegendInfos property on the map is set to true. That will make sure all the legend infos came down automatically without extra work on your part.
After that, if your symbol types in the model are SimpleLineSymbol types, you should be able to pull out the color.
Here's a minor tweak I added to the sample I mentioned. It shows the basic idea of accessing each LegendInfo from the model's delegate and printing the color if it's a SimpleLineSymbol.
// Create a list view to display the legend
ListView {
id: legendListView
anchors.margins: 10
width: 165
height: 150
clip: true
model: map.legendInfos
// Create delegate to display the name with an image
delegate: Item {
width: parent ? parent.width : 0
height: 35
clip: true
Row {
Component.onCompleted: {
if (index !== -1) {
let symbol = map.legendInfos.get(index).symbol;
if (symbol && symbol.symbolType === Enums.SymbolTypeSimpleLineSymbol) {
// this symbol is a simple line symbol, print the color
console.log(symbol.color);
}
}
}
Let us know if this helps.
Thank you, yes, this is helpful to get a hook into when I can grab those colors. I didn't know you could add a completed signal to the Row, good to know. I'm still not getting the name property of the legendInfo item back however. It is an empty string which makes me wonder if it has to do with the source web map and\or how it is handled. Any insights there would be much appreciated.
@DavidPuckett interesting, yes could be something with the data. I am getting the name printed out, but it does depend on which legendInfo it is, and it will also depend on the source data online and whether that contains any name info.
Row {
Component.onCompleted: {
if (index !== -1) {
let legendInfo = map.legendInfos.get(index);
console.log(legendInfo.name);
}
}
Using that with the sample prints as follows as I scroll through the legend:
qml: 0 - 61
qml: 62 - 264
qml: 265 - 759
qml: 760 - 1900
qml: 1901 - 9409
qml:
qml:
qml:
qml: Camping
qml: Dining
qml: Drinking Water
qml: Medical Facility
You can see that some of the legend entries here don't contain any "label"
https://sampleserver6.arcgisonline.com/arcgis/rest/services/Census/MapServer/legend?f=pjson
Right, this is interesting. First, it appears that the 'name' property in legendInfo is the 'label' in the legend item. And, if there is only a single symbol for the layer, the name is not included in the legendInfo item. This is a good explanation of what's going on albeit a little confusing to navigate. So really what I was after was the layerName and that isn't found within legendInfos. Now if I were using unique symbols for example it would be useful.
So ultimately, for my situation, getting the symbol colors directly from the layer renderers was the solution.
This latest example provided the clarity to get there and hopefully others with issues around legendInfos will find it useful.