diff --git a/lib/layer/styleParser.mjs b/lib/layer/styleParser.mjs index 5acb3c94e..31a33f29d 100644 --- a/lib/layer/styleParser.mjs +++ b/lib/layer/styleParser.mjs @@ -289,6 +289,27 @@ export default layer => { styleObject(cat, structuredClone(layer.style.default)) }) + + // Check validity of categorized theme with multiple fields. + if (theme.type === 'categorized' && Array.isArray(theme.fields)) { + + theme.categories.forEach(cat => { + + if (!theme.fields.includes(cat.field)) { + + console.warn(`Layer: ${layer.key}; Cat ${cat.label} missed valid field.`) + } + + // Multiple field cat theme style must be icon. + if (!cat.style.icon) { + + console.warn(`Layer: ${layer.key}; Cat ${cat.label} has invalid icon style.`) + + cat.style.icon = { type: 'dot' } + } + }) + + } } /** @@ -314,8 +335,15 @@ export default layer => { if (cat.style.icon) { + // Do not merge default style into icon array. if (Array.isArray(cat.style.icon)) return; + // Do not merge default style into icon with type definition. + if (cat.style.icon.type) return; + + // Do not merge default style into svg [type] icons. + if (cat.style.icon.svg) return; + if (defaultStyle.icon && !Array.isArray(defaultStyle.icon)) { cat.style.icon = { diff --git a/lib/layer/themes/categorized.mjs b/lib/layer/themes/categorized.mjs index c1f999b0f..40315d751 100644 --- a/lib/layer/themes/categorized.mjs +++ b/lib/layer/themes/categorized.mjs @@ -1,21 +1,30 @@ /** ### mapp.layer.themes.categorized() -This module exports a function that applies a categorized theme to a feature based on a specified field value. + +The module exports the categorized function as a mapp.layer.theme. + @module /layer/themes/categorized - */ +*/ /** +@function categorized + +@description +The categorized theme method will assign a style from category matching the features properties. + +Cluster features may not be styled by a categorized theme. - * @function categorized - * @param {Object} theme - The theme configuration object. - * @param {string} theme.field - The field name used for determining the category. - * @param {Array} theme.categories - An array of category objects. - * @param {Object} feature - The feature object. - * @param {Object} feature.properties - The properties of the feature. - * @param {Array} [feature.properties.features] - An array of clustered features. - * @returns {void} - */ -export default function (theme, feature) { +A theme can have a fields array to apply an icon style array for the individual property fields. + +@param {Object} theme The theme configuration object. +@param {string} [theme.field] The feature property field to theme. +@param {array} [theme.fields] A fields array to style multiple feature properties. +@param {Array} theme.categories +@param {Object} feature +@param {Object} feature.properties +@param {Array} [feature.properties.features] A cluster feature will have a features array property. +*/ +export default function categorized(theme, feature) { // The categorized theme requires feature.properties. if (!feature.properties) return; @@ -23,6 +32,37 @@ export default function (theme, feature) { // Cluster features can not be styled by category. if (feature.properties.features?.length > 1) return; + let flat; + + // Theme is using multiple fields. + if (Array.isArray(theme.fields)) { + + // Map different theme fields + feature.style.icon = theme.fields.map(field => { + + // Get the field value from feature properties + const catValue = feature.properties[field] + + // Find category matching field and catValue + const cat = theme.categories.find(cat => (cat.value === encodeURIComponent(catValue) || cat.value === catValue) && cat.field === field) + + if (!cat) return; + + flat ||= Array.isArray(cat.style.icon) + + return cat.style.icon + + // Filter out empty icon entries from map response. + }).filter(icon => !!icon); + + if (flat) { + + feature.style.icon = feature.style.icon.flat() + } + + return; + } + const catValue = feature.properties[theme.field] const cat = theme.categories.find(cat => cat.value === encodeURIComponent(catValue) || cat.value === catValue) diff --git a/lib/ui/layers/legends/categorized.mjs b/lib/ui/layers/legends/categorized.mjs index 8b3d744e9..bf6aaf591 100644 --- a/lib/ui/layers/legends/categorized.mjs +++ b/lib/ui/layers/legends/categorized.mjs @@ -13,7 +13,7 @@ export default (layer) => { let timeout; // Switch all control - theme.legend.switch = layer.filter && mapp.utils.html` + theme.legend.switch = theme.field && layer.filter && mapp.utils.html`