From d588ad2b40ca46a4466791832c6215b97a083914 Mon Sep 17 00:00:00 2001 From: Lauren Date: Tue, 14 Nov 2023 12:38:47 -0500 Subject: [PATCH 01/18] feat: Add color scheme selection and colorblind modes to Preferences UI Add default and example color scheme objects to colors.json. Minify colors.json in build_data.js. Add colors.json to DataLoaderSystem's fileMap. Add color scheme helper functions to StyleSytem, with comments to describe each functions parameters and return values (where applicable). Update StyleSystem's styleMatch() function to interact with color scheme objects from colors.json rather than from STYLE_DECLARATIONS. Fix white space discrepancies in StyleSystem. Update color_selection.js and colorblind_mode_options.js to use StyleSystem rather than the non-existent ColorSystem. Uncomment color schemes and colorblind mode options sections in preferences.js to add them to the Preferences pane of the UI. Refs: Issue #1230 --- data/colors.json | 78 +++++++++++ modules/core/DataLoaderSystem.js | 1 + modules/core/StyleSystem.js | 128 +++++++++++------- modules/ui/panes/preferences.js | 8 +- modules/ui/sections/color_selection.js | 16 +-- .../ui/sections/colorblind_mode_options.js | 12 +- scripts/build_data.js | 1 + 7 files changed, 176 insertions(+), 68 deletions(-) create mode 100644 data/colors.json diff --git a/data/colors.json b/data/colors.json new file mode 100644 index 0000000000..6b675aed3a --- /dev/null +++ b/data/colors.json @@ -0,0 +1,78 @@ +{ + "default": { + "red": { + "fill": { "color": "0xe06e5f", "alpha": 0.3 } + }, + "green": { + "fill": { "color": "0x8cd05f", "alpha": 0.3 } + }, + "blue": { + "fill": { "color": "0x77d4de", "alpha": 0.3 } + }, + "yellow": { + "fill": { "color": "0xffff94", "alpha": 0.25 } + }, + "gold": { + "fill": { "color": "0xc4be19", "alpha": 0.3 } + }, + "orange": { + "fill": { "color": "0xd6881a", "alpha": 0.3 } + }, + "pink": { + "fill": { "color": "0xe3a4f5", "alpha": 0.3 } + }, + "teal": { + "fill": { "color": "0x99e1aa", "alpha": 0.3 } + }, + "lightgreen": { + "fill": { "color": "0xbee83f", "alpha": 0.3 } + }, + "tan": { + "fill": { "color": "0xf5dcba", "alpha": 0.3 } + }, + "darkgray": { + "fill": { "color": "0x8c8c8c", "alpha": 0.5 } + }, + "lightgray": { + "fill": { "color": "0xaaaaaa", "alpha": 0.3 } + } + }, + "example": { + "red": { + "fill": { "color": "0xFF0E41", "alpha": 0.3 } + }, + "green": { + "fill": { "color": "0x09F04A", "alpha": 0.3 } + }, + "blue": { + "fill": { "color": "0x0CBCFF", "alpha": 0.3 } + }, + "yellow": { + "fill": { "color": "0xFFCA09", "alpha": 0.25 } + }, + "gold": { + "fill": { "color": "0xFF0EBC", "alpha": 0.3 } + }, + "orange": { + "fill": { "color": "0xFF510B", "alpha": 0.3 } + }, + "pink": { + "fill": { "color": "0xF1C0E8", "alpha": 0.3 } + }, + "teal": { + "fill": { "color": "0x12FFD1", "alpha": 0.3 } + }, + "lightgreen": { + "fill": { "color": "0x540FFF", "alpha": 0.3 } + }, + "tan": { + "fill": { "color": "0xAFFA1F", "alpha": 0.3 } + }, + "darkgray": { + "fill": { "color": "0x0000FE", "alpha": 0.5 } + }, + "lightgray": { + "fill": { "color": "0xE9AF1E", "alpha": 0.3 } + } + } +} diff --git a/modules/core/DataLoaderSystem.js b/modules/core/DataLoaderSystem.js index 810beb269a..13ee6e6c32 100644 --- a/modules/core/DataLoaderSystem.js +++ b/modules/core/DataLoaderSystem.js @@ -23,6 +23,7 @@ export class DataLoaderSystem extends AbstractSystem { const fileMap = new Map(); fileMap.set('address_formats', 'data/address_formats.min.json'); + fileMap.set('colors', 'data/colors.min.json'); fileMap.set('deprecated', 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@6.6/dist/deprecated.min.json'); fileMap.set('discarded', 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@6.6/dist/discarded.min.json'); fileMap.set('imagery', 'data/imagery.min.json'); diff --git a/modules/core/StyleSystem.js b/modules/core/StyleSystem.js index 4beb1a4671..e11477fa90 100644 --- a/modules/core/StyleSystem.js +++ b/modules/core/StyleSystem.js @@ -36,6 +36,11 @@ export class StyleSystem extends AbstractSystem { this.dependencies = new Set(['dataloader']); this.autoStart = true; + // To handle color schemes + this.colorData = null; + this.colorSchemes = null; + this.currentColorScheme = null; + // Experiment, see Rapid#1230 // matrix values from https://github.com/maputnik/editor this.protanopiaMatrix = [ @@ -98,43 +103,6 @@ export class StyleSystem extends AbstractSystem { stroke: { dash: [7, 3], cap: 'butt' } }, - red: { - fill: { color: 0xe06e5f, alpha: 0.3 } // rgb(224, 110, 95) - }, - green: { - fill: { color: 0x8cd05f, alpha: 0.3 } // rgb(140, 208, 95) - }, - blue: { - fill: { color: 0x77d4de, alpha: 0.3 } // rgb(119, 211, 222) - }, - yellow: { - fill: { color: 0xffff94, alpha: 0.25 } // rgb(255, 255, 148) - }, - gold: { - fill: { color: 0xc4be19, alpha: 0.3 } // rgb(196, 189, 25) - }, - orange: { - fill: { color: 0xd6881a, alpha: 0.3 } // rgb(214, 136, 26) - }, - pink: { - fill: { color: 0xe3a4f5, alpha: 0.3 } // rgb(228, 164, 245) - }, - teal: { - fill: { color: 0x99e1aa, alpha: 0.3 } // rgb(153, 225, 170) - }, - lightgreen: { - fill: { color: 0xbee83f, alpha: 0.3 } // rgb(191, 232, 63) - }, - tan: { - fill: { color: 0xf5dcba, alpha: 0.3 } // rgb(245, 220, 186) - }, - darkgray: { - fill: { color: 0x8c8c8c, alpha: 0.5 } // rgb(140, 140, 140) - }, - lightgray: { - fill: { color: 0xaaaaaa, alpha: 0.3 } // rgb(170, 170, 170) - }, - motorway: { casing: { width: 10, color: 0x70372f }, stroke: { width: 8, color: 0xcf2081 } @@ -216,17 +184,17 @@ export class StyleSystem extends AbstractSystem { stroke: { width: 3, color: 0x81d25c, dash: [3, 3], cap: 'butt' } }, river: { - fill: { color: 0x77d4de, alpha: 0.3 }, // rgb(119, 211, 222) + fill: { color: 0x77d4de, alpha: 0.3 }, // rgb(119, 211, 222) casing: { width: 10, color: 0x444444 }, stroke: { width: 8, color: 0x77dddd } }, stream: { - fill: { color: 0x77d4de, alpha: 0.3 }, // rgb(119, 211, 222) + fill: { color: 0x77d4de, alpha: 0.3 }, // rgb(119, 211, 222) casing: { width: 7, color: 0x444444 }, stroke: { width: 5, color: 0x77dddd } }, ridge: { - stroke: { width: 2, color: 0x8cd05f} // rgb(140, 208, 95) + stroke: { width: 2, color: 0x8cd05f } // rgb(140, 208, 95) }, runway: { casing: { width: 10, color: 0x000000, cap: 'butt' }, @@ -261,7 +229,7 @@ export class StyleSystem extends AbstractSystem { stroke: { width: 3, color: 0xdddddd, dash: [10, 5, 2, 5], cap: 'round' } }, barrier_hedge: { - fill: { color: 0x8cd05f, alpha: 0.3 }, // rgb(140, 208, 95) + fill: { color: 0x8cd05f, alpha: 0.3 }, // rgb(140, 208, 95) casing: { alpha: 0 }, // disable stroke: { width: 3, color: 0x8cd05f, dash: [10, 5, 2, 5], cap: 'round' } }, @@ -270,7 +238,7 @@ export class StyleSystem extends AbstractSystem { stroke: { width: 5, color: 0x8cd05f } }, construction: { - casing: { width: 10, color: 0xffffff}, + casing: { width: 10, color: 0xffffff }, stroke: { width: 8, color: 0xfc6c14, dash: [10, 10], cap: 'butt' } }, pipeline: { @@ -553,6 +521,10 @@ export class StyleSystem extends AbstractSystem { this.styleMatch = this.styleMatch.bind(this); + + // To handle color schemes + this.getColorScheme = this.getColorScheme.bind(this); + this.getAllColorSchemes = this.getAllColorSchemes.bind(this); } @@ -561,10 +533,10 @@ export class StyleSystem extends AbstractSystem { * Called after all core objects have been constructed. * @return {Promise} Promise resolved when this component has completed initialization */ - initAsync(){ + initAsync() { for (const id of this.dependencies) { if (!this.context.systems[id]) { - return Promise.reject(`Cannot init: ${this.id} requires ${id}`); + return Promise.reject(`Cannot init: ${this.id} requires ${id}`); } } return Promise.resolve(); @@ -577,6 +549,20 @@ export class StyleSystem extends AbstractSystem { */ startAsync() { this._started = true; + + // To handle color schemes + const context = this.context; + const dataloader = context.systems.dataloader; + + dataloader.getDataAsync('colors') + .then((data) => { + this.colorSchemes = data; + // set current scheme to default + this.colorData = data.default; + this.currentColorScheme = 'default'; + this.emit('colorsloaded'); // emit copies + }); + return Promise.resolve(); } @@ -590,6 +576,34 @@ export class StyleSystem extends AbstractSystem { return Promise.resolve(); } + /** + * getColorScheme + * @return {Object} Default color scheme object + */ + getColorScheme() { + return this.colorData; + } + + /** + * getAllColorSchemeas + * @return {Object} All color scheme objects + */ + getAllColorSchemes() { + return this.colorSchemes; + } + + /** + * setColorScheme + * Assigns the colorData var to the new scheme, if the selected scheme is not the current scheme + * @param {Object} scheme - color scheme project + */ + setColorScheme(scheme) { + let currentScheme = this.colorSchemes[scheme]; + if (this.colorData !== currentScheme) { + this.currentColorScheme = scheme; + this.colorData = currentScheme; + } + } /** * styleMatch @@ -603,6 +617,7 @@ export class StyleSystem extends AbstractSystem { let styleScore = 999; // lower numbers are better let styleKey; // the key controlling the styling, if any let styleVal; // the value controlling the styling, if any + let colorScheme = this.getColorScheme(); // First, match the tags to the best matching `styleID`.. for (const [k, v] of Object.entries(tags)) { @@ -617,13 +632,13 @@ export class StyleSystem extends AbstractSystem { if (lifecycleVals.has(v)) score = 999; // exception: lifecycle values if (styleID && score <= styleScore) { - const declaration = this.STYLE_DECLARATIONS[styleID]; + const declaration = this.STYLE_DECLARATIONS[styleID] || colorScheme[styleID]; if (!declaration) { console.error(`invalid styleID: ${styleID}`); // eslint-disable-line continue; } - matched = declaration; + matched = declaration || currentScheme; styleScore = score; styleKey = k; styleVal = v; @@ -643,14 +658,14 @@ export class StyleSystem extends AbstractSystem { hasLifecycleTag = true; break; - // Lifecycle value, e.g. `railway=demolished` - // (applies only if `k` is styleKey or there is no styleKey controlling styling) + // Lifecycle value, e.g. `railway=demolished` + // (applies only if `k` is styleKey or there is no styleKey controlling styling) } else if ((!styleKey || k === styleKey) && lifecycleVals.has(v)) { hasLifecycleTag = true; break; - // Lifecycle key prefix, e.g. `demolished:railway=rail` - // (applies only if there is no styleKey controlling the styling) + // Lifecycle key prefix, e.g. `demolished:railway=rail` + // (applies only if there is no styleKey controlling the styling) } else if (!styleKey && lifecycleRegex.test(k) && v !== 'no') { hasLifecycleTag = true; break; @@ -763,4 +778,17 @@ export class StyleSystem extends AbstractSystem { return tags[key] === 'no' ? undefined : tags[key]; } } + + // Returns object containing all color scheme objects + getAllColorSchemes() { + return this.STYLE_SCHEMES; + } + + // Sets map color scheme + setColorScheme(schemeName) { + let currentScheme = this.STYLE_SCHEMES[schemeName]; + if (this.currentColorScheme !== currentScheme) { + this.currentColorScheme = currentScheme; + } + } } diff --git a/modules/ui/panes/preferences.js b/modules/ui/panes/preferences.js index b9ab5ce188..228b83ef57 100644 --- a/modules/ui/panes/preferences.js +++ b/modules/ui/panes/preferences.js @@ -1,8 +1,8 @@ import { uiPane } from '../pane.js'; import { uiSectionPrivacy } from '../sections/privacy.js'; -//import { uiSectionColorSelection } from '../sections/color_selection.js'; -//import { uiSectionColorblindModeOptions } from '../sections/colorblind_mode_options.js'; import { uiSectionMapInteractionOptions } from '../sections/map_interaction_options.js'; +import { uiSectionColorSelection } from '../sections/color_selection.js'; +import { uiSectionColorblindModeOptions } from '../sections/colorblind_mode_options.js'; export function uiPanePreferences(context) { @@ -16,7 +16,7 @@ export function uiPanePreferences(context) { .sections([ uiSectionPrivacy(context), uiSectionMapInteractionOptions(context), -// uiSectionColorSelection(context), -// uiSectionColorblindModeOptions(context) + uiSectionColorSelection(context), + uiSectionColorblindModeOptions(context) ]); } diff --git a/modules/ui/sections/color_selection.js b/modules/ui/sections/color_selection.js index b7ca52679b..abb9a05374 100644 --- a/modules/ui/sections/color_selection.js +++ b/modules/ui/sections/color_selection.js @@ -3,19 +3,18 @@ import { uiCombobox } from '../combobox.js'; import { uiSection } from '../section.js'; import { utilNoAuto } from '../../util/index.js'; - export function uiSectionColorSelection(context) { const l10n = context.systems.l10n; - const colors = context.systems.colors; // todo: replace + const styles = context.systems.styles; // Add or replace event handlers - colors.off('colorsloaded', loadComboBoxData); - colors.on('colorsloaded', loadComboBoxData); + styles.off('colorsloaded', loadComboBoxData); + styles.on('colorsloaded', loadComboBoxData); let comboData = []; function loadComboBoxData(){ - let colorSchemeKeys = Object.keys(colors.getAllColorSchemes()); + let colorSchemeKeys = Object.keys(styles.getAllColorSchemes()); for (let i = 0; i < colorSchemeKeys.length; i++) { let colorObject = {}; @@ -27,9 +26,10 @@ export function uiSectionColorSelection(context) { return comboData; } + comboData = loadComboBoxData(); const section = uiSection(context, 'preferences-color-selection') - .label(l10n.tHtml('preferences.color_selection.title')) + .label(l10n.t('preferences.color_selection.title')) .disclosureContent(renderDisclosureContent); const colorCombo = uiCombobox(context, 'color-selection'); @@ -63,8 +63,8 @@ export function uiSectionColorSelection(context) { _colorSelectedId = val; let colorSchemeName = getColorSchemeName(_colorSelectedId); - if (colors.currentColorScheme !== colorSchemeName) { - colors.setColorScheme(colorSchemeName); + if (styles.currentColorScheme !== colorSchemeName) { + styles.setColorScheme(colorSchemeName); context.scene().dirtyScene(); context.systems.map.deferredRedraw(); } diff --git a/modules/ui/sections/colorblind_mode_options.js b/modules/ui/sections/colorblind_mode_options.js index a5cc99f5eb..6f29b5b7a8 100644 --- a/modules/ui/sections/colorblind_mode_options.js +++ b/modules/ui/sections/colorblind_mode_options.js @@ -7,7 +7,7 @@ import { utilNoAuto } from '../../util/index.js'; export function uiSectionColorblindModeOptions(context) { const l10n = context.systems.l10n; - const colors = context.systems.colors; // todo: replace + const styles = context.systems.styles; let comboData = [{ title: 'default', value: l10n.t('preferences.colorblind_options.default') }]; @@ -20,16 +20,16 @@ export function uiSectionColorblindModeOptions(context) { const filtersObject = { 'Protanopia': protanopiaFilter, 'Deuteranopia': deuteranopiaFilter, 'Tritanopia': tritanopiaFilter }; // color matrices - const protanopiaMatrix = colors.protanopiaMatrix; - const deuteranopiaMatrix = colors.deuteranopiaMatrix; - const tritanopiaMatrix = colors.tritanopiaMatrix; + const protanopiaMatrix = styles.protanopiaMatrix; + const deuteranopiaMatrix = styles.deuteranopiaMatrix; + const tritanopiaMatrix = styles.tritanopiaMatrix; // apply color matrices to filters protanopiaFilter.matrix = protanopiaMatrix; deuteranopiaFilter.matrix = deuteranopiaMatrix; tritanopiaFilter.matrix = tritanopiaMatrix; - function loadComboBoxData(){ + function loadComboBoxData() { let colorblindModes = Object.keys(filtersObject); for (let i = 0; i < colorblindModes.length; i++) { @@ -45,7 +45,7 @@ export function uiSectionColorblindModeOptions(context) { loadComboBoxData(); const section = uiSection(context, 'preferences-colorblind-mode-options') - .label(l10n.tHtml('preferences.colorblind_options.title')) + .label(l10n.t('preferences.colorblind_options.title')) .disclosureContent(renderDisclosureContent); const colorblindCombo = uiCombobox(context, 'colorblind-mode-options'); diff --git a/scripts/build_data.js b/scripts/build_data.js index 4c28000ab7..3698a018ce 100644 --- a/scripts/build_data.js +++ b/scripts/build_data.js @@ -99,6 +99,7 @@ function buildData() { minifySync('data/qa_data.json', 'dist/data/qa_data.min.json'); minifySync('data/shortcuts.json', 'dist/data/shortcuts.min.json'); minifySync('data/territory_languages.json', 'dist/data/territory_languages.min.json'); + minifySync('data/colors.json', 'dist/data/colors.min.json') return _currBuild = Promise.resolve(true) .then(() => { From 1a85cbd12e4d2f346f48d705da64d9d057706d4e Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Fri, 12 Apr 2024 01:15:36 +0100 Subject: [PATCH 02/18] feat: Implement restructured color system --- data/colors_definition.json | 65 +++++++++++++++++++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 data/colors_definition.json diff --git a/data/colors_definition.json b/data/colors_definition.json new file mode 100644 index 0000000000..4c3454b0c3 --- /dev/null +++ b/data/colors_definition.json @@ -0,0 +1,65 @@ +{ + "default": { + "red": { + "red-1": "0xe06e5f", + "red-2": "0xe06d5f", + "red-3": "0xdd2f22", + "red-4": "0x70372f" + }, + "orange": { + "orange-1": "0xf99806", + "orange-2": "0xd6881a", + "orange-3": "0xfc6c14" + }, + "yellow": { + "yellow-1": "0xfff9b3", + "yellow-2": "0xffff94", + "yellow-3": "0xffff00", + "yellow-4": "0xf3f312", + "yellow-5": "0xc4be19" + }, + "green": { + "green-1": "0x99e1aa", + "green-2": "0xb0e298", + "green-3": "0x8cd05f", + "green-4": "0x81d25c", + "green-5": "0xbee83f" + }, + "blue": { + "blue-1": "0x77dddd", + "blue-2": "0x77d4de", + "blue-3": "0x82b5fe", + "blue-4": "0x58a9ed" + }, + "pink": { + "pink-1": "0xe3a4f5", + "pink-2": "0xcf2081" + }, + "brown": { + "brown-1": "0x998888", + "brown-2": "0x776a6a", + "brown-3": "0x746f6f", + "brown-4": "0x4c4444" + }, + "tan": { + "tan-1": "0xf5dcba", + "tan-2": "0xddccaa", + "tan-3": "0xc5b59f" + }, + "white": { + "white-0": "0xffffff" + }, + "black": { + "black-0": "0x000000" + }, + "grey": { + "gray-1": "0xeeeeee", + "gray-2": "0xdddddd", + "gray-3": "0xcccccc", + "gray-4": "0xaaaaaa", + "gray-5": "0x8c8c8c", + "gray-6": "0x555555", + "gray-7": "0x444444" + } + } +} \ No newline at end of file From 4b9a8e2975e8793548b618708727939636710f7d Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Fri, 12 Apr 2024 04:42:48 +0100 Subject: [PATCH 03/18] refactor: Enable code to use the created color system Extract the style definitions to a separate folder, including style definitions which were in colors.json. Add abstracted color and style definitions to minification and data loading files. Load the style definitions alongside color loading in StyleSystem.js. Update style selectors to use newly abstracted style definitions. Map colors defined in the color system to their hex codes. in StyleSystem.js. Reduce the boilerplate code in style matching in StyleSystem.js. --- ...ors_definition.json => color_schemes.json} | 2 +- data/styles.json | 196 +++++++++++ modules/core/DataLoaderSystem.js | 2 + modules/core/StyleSystem.js | 315 +++++------------- scripts/build_data.js | 4 +- 5 files changed, 286 insertions(+), 233 deletions(-) rename data/{colors_definition.json => color_schemes.json} (98%) create mode 100644 data/styles.json diff --git a/data/colors_definition.json b/data/color_schemes.json similarity index 98% rename from data/colors_definition.json rename to data/color_schemes.json index 4c3454b0c3..83dfdce20c 100644 --- a/data/colors_definition.json +++ b/data/color_schemes.json @@ -52,7 +52,7 @@ "black": { "black-0": "0x000000" }, - "grey": { + "gray": { "gray-1": "0xeeeeee", "gray-2": "0xdddddd", "gray-3": "0xcccccc", diff --git a/data/styles.json b/data/styles.json new file mode 100644 index 0000000000..e5237eeb0c --- /dev/null +++ b/data/styles.json @@ -0,0 +1,196 @@ +{ + "DEFAULTS": { + "fill": { "width": 2, "color": "gray-4", "alpha": 0.3 }, + "casing": { "width": 5, "color": "gray-7", "alpha": 1, "cap": "round", "join": "round" }, + "stroke": { "width": 3, "color": "gray-3", "alpha": 1, "cap": "round", "join": "round" } + }, + + "LIFECYCLE": { + "casing": { "alpha": 0 }, + "stroke": { "dash": [7, 3], "cap": "butt" } + }, + + "common-red": { + "fill": { "color": "red-1", "alpha": 0.3 } + }, + "common-green": { + "fill": { "color": "green-3", "alpha": 0.3 } + }, + "common-blue": { + "fill": { "color": "blue-2", "alpha": 0.3 } + }, + "common-yellow": { + "fill": { "color": "yellow-2", "alpha": 0.25 } + }, + "common-gold": { + "fill": { "color": "yellow-5", "alpha": 0.3 } + }, + "common-orange": { + "fill": { "color": "orange-2", "alpha": 0.3 } + }, + "common-pink": { + "fill": { "color": "pink-1", "alpha": 0.3 } + }, + "common-teal": { + "fill": { "color": "green-1", "alpha": 0.3 } + }, + "common-lightgreen": { + "fill": { "color": "green-5", "alpha": 0.3 } + }, + "common-tan": { + "fill": { "color": "tan-1", "alpha": 0.3 } + }, + "common-darkgray": { + "fill": { "color": "gray-6", "alpha": 0.5 } + }, + "common-lightgray": { + "fill": { "color": "gray-7", "alpha": 0.3 } + }, + + "motorway": { + "casing": { "width": 10, "color": "red-4" }, + "stroke": { "width": 8, "color": "pink-2" } + }, + "trunk": { + "casing": { "width": 10, "color": "red-4" }, + "stroke": { "width": 8, "color": "red-3" } + }, + "primary": { + "casing": { "width": 10, "color": "red-4" }, + "stroke": { "width": 8, "color": "orange-1" } + }, + "secondary": { + "casing": { "width": 10, "color": "red-4" }, + "stroke": { "width": 8, "color": "yellow-4" } + }, + "tertiary": { + "casing": { "width": 10, "color": "red-4" }, + "stroke": { "width": 8, "color": "yellow-1" } + }, + "unclassified": { + "casing": { "width": 10, "color": "gray-7" }, + "stroke": { "width": 8, "color": "tan-2" } + }, + "residential": { + "casing": { "width": 10, "color": "gray-7" }, + "stroke": { "width": 8, "color": "white-0" } + }, + "living_street": { + "casing": { "width": 7, "color": "white-0" }, + "stroke": { "width": 5, "color": "gray-3" } + }, + "service": { + "casing": { "width": 7, "color": "gray-7" }, + "stroke": { "width": 5, "color": "white-0" } + }, + "special_service": { + "casing": { "width": 7, "color": "gray-7" }, + "stroke": { "width": 5, "color": "tan-2" } + }, + "track": { + "casing": { "width": 7, "color": "brown-3" }, + "stroke": { "width": 5, "color": "tan-3" } + }, + "pedestrian": { + "casing": { "width": 7, "color": "white-0" }, + "stroke": { "width": 5, "color": "brown-1", "dash": [8, 8], "cap": "butt" } + }, + "path": { + "casing": { "width": 5, "color": "tan-2" }, + "stroke": { "width": 3, "color": "brown-1", "dash": [6, 6], "cap": "butt" } + }, + "footway": { + "casing": { "width": 5, "color": "white-0" }, + "stroke": { "width": 3, "color": "brown-1", "dash": [6, 6], "cap": "butt" } + }, + "crossing_marked": { + "casing": { "width": 5, "color": "tan-2" }, + "stroke": { "width": 3, "color": "brown-4", "dash": [6, 3], "cap": "butt" } + }, + "crossing_unmarked": { + "casing": { "width": 5, "color": "tan-2" }, + "stroke": { "width": 3, "color": "brown-2", "dash": [6, 4], "cap": "butt" } + }, + "cycleway": { + "casing": { "width": 5, "color": "white-0" }, + "stroke": { "width": 3, "color": "blue-4", "dash": [6, 6], "cap": "butt" } + }, + "bridleway": { + "casing": { "width": 5, "color": "white-0" }, + "stroke": { "width": 3, "color": "red-2", "dash": [6, 6], "cap": "butt" } + }, + "corridor": { + "casing": { "width": 5, "color": "white-0" }, + "stroke": { "width": 3, "color": "green-3", "dash": [2, 8], "cap": "round" } + }, + "steps": { + "casing": { "width": 5, "color": "white-0" }, + "stroke": { "width": 3, "color": "green-4", "dash": [3, 3], "cap": "butt" } + }, + "river": { + "fill": { "color": "blue-2", "alpha": 0.3 }, + "casing": { "width": 10, "color": "gray-7" }, + "stroke": { "width": 8, "color": "blue-1" } + }, + "stream": { + "fill": { "color": "blue-2", "alpha": 0.3 }, + "casing": { "width": 7, "color": "gray-7" }, + "stroke": { "width": 5, "color": "blue-1" } + }, + "ridge": { + "stroke": { "width": 2, "color": "green-3" } + }, + "runway": { + "casing": { "width": 10, "color": "black-0", "cap": "butt" }, + "stroke": { "width": 8, "color": "white-0", "dash": [24, 48], "cap": "butt" } + }, + "taxiway": { + "casing": { "width": 7, "color": "gray-7" }, + "stroke": { "width": 5, "color": "yellow-3" } + }, + "railway": { + "casing": { "width": 7, "color": "gray-6", "cap": "butt" }, + "stroke": { "width": 2, "color": "gray-1", "dash": [12, 12], "cap": "butt" } + }, + "ferry": { + "casing": { "alpha": 0 }, + "stroke": { "width": 3, "color": "blue-4", "dash": [12, 8], "cap": "butt" } + }, + "boundary": { + "casing": { "width": 6, "color": "blue-3", "cap": "butt" }, + "stroke": { "width": 2, "color": "white-0", "dash": [20, 5, 5, 5], "cap": "butt" } + }, + "boundary_park": { + "casing": { "width": 6, "color": "blue-3", "cap": "butt" }, + "stroke": { "width": 2, "color": "green-2", "dash": [20, 5, 5, 5], "cap": "butt" } + }, + "barrier": { + "casing": { "alpha": 0 }, + "stroke": { "width": 3, "color": "gray-2", "dash": [10, 5, 2, 5], "cap": "round" } + }, + "barrier_wall": { + "casing": { "alpha": 0 }, + "stroke": { "width": 3, "color": "gray-2", "dash": [10, 5, 2, 5], "cap": "round" } + }, + "barrier_hedge": { + "fill": { "color": "green-3", "alpha": 0.3 }, + "casing": { "alpha": 0 }, + "stroke": { "width": 3, "color": "green-3", "dash": [10, 5, 2, 5], "cap": "round" } + }, + "tree_row": { + "casing": { "width": 7, "color": "gray-7" }, + "stroke": { "width": 5, "color": "green-3" } + }, + "construction": { + "casing": { "width": 10, "color": "white-0" }, + "stroke": { "width": 8, "color": "orange-3", "dash": [10, 10], "cap": "butt" } + }, + "pipeline": { + "casing": { "width": 7, "color": "gray-7" }, + "stroke": { "width": 5, "color": "gray-2", "dash": [80, 2], "cap": "butt" } + }, + "roller_coaster": { + "casing": { "width": 7, "color": "gray-7" }, + "stroke": { "width": 5, "color": "gray-2", "dash": [10, 1], "cap": "butt" } + } +} \ No newline at end of file diff --git a/modules/core/DataLoaderSystem.js b/modules/core/DataLoaderSystem.js index 13ee6e6c32..7eea9765c5 100644 --- a/modules/core/DataLoaderSystem.js +++ b/modules/core/DataLoaderSystem.js @@ -23,6 +23,7 @@ export class DataLoaderSystem extends AbstractSystem { const fileMap = new Map(); fileMap.set('address_formats', 'data/address_formats.min.json'); + fileMap.set('color_schemes', 'data/color_schemes.min.json'); fileMap.set('colors', 'data/colors.min.json'); fileMap.set('deprecated', 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@6.6/dist/deprecated.min.json'); fileMap.set('discarded', 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@6.6/dist/discarded.min.json'); @@ -43,6 +44,7 @@ export class DataLoaderSystem extends AbstractSystem { fileMap.set('preset_overrides', 'data/preset_overrides.min.json'); fileMap.set('qa_data', 'data/qa_data.min.json'); fileMap.set('shortcuts', 'data/shortcuts.min.json'); + fileMap.set('styles', 'data/styles.min.json'); fileMap.set('territory_languages', 'data/territory_languages.min.json'); fileMap.set('wmf_sitematrix', 'https://cdn.jsdelivr.net/npm/wmf-sitematrix@0.1/wikipedia.min.json'); diff --git a/modules/core/StyleSystem.js b/modules/core/StyleSystem.js index e11477fa90..4ed16ab8c9 100644 --- a/modules/core/StyleSystem.js +++ b/modules/core/StyleSystem.js @@ -91,165 +91,7 @@ export class StyleSystem extends AbstractSystem { // `pattern` - supported pattern (see dist/img/pattern/* for these) // - this.STYLE_DECLARATIONS = { - DEFAULTS: { - fill: { width: 2, color: 0xaaaaaa, alpha: 0.3 }, - casing: { width: 5, color: 0x444444, alpha: 1, cap: 'round', join: 'round' }, - stroke: { width: 3, color: 0xcccccc, alpha: 1, cap: 'round', join: 'round' } - }, - - LIFECYCLE: { // e.g. planned, proposed, abandoned, disused, razed - casing: { alpha: 0 }, // disable - stroke: { dash: [7, 3], cap: 'butt' } - }, - - motorway: { - casing: { width: 10, color: 0x70372f }, - stroke: { width: 8, color: 0xcf2081 } - }, - trunk: { - casing: { width: 10, color: 0x70372f }, - stroke: { width: 8, color: 0xdd2f22 } - }, - primary: { - casing: { width: 10, color: 0x70372f }, - stroke: { width: 8, color: 0xf99806 } - }, - secondary: { - casing: { width: 10, color: 0x70372f }, - stroke: { width: 8, color: 0xf3f312 } - }, - tertiary: { - casing: { width: 10, color: 0x70372f }, - stroke: { width: 8, color: 0xfff9b3 } - }, - unclassified: { - casing: { width: 10, color: 0x444444 }, - stroke: { width: 8, color: 0xddccaa } - }, - residential: { - casing: { width: 10, color: 0x444444 }, - stroke: { width: 8, color: 0xffffff } - }, - living_street: { - casing: { width: 7, color: 0xffffff }, - stroke: { width: 5, color: 0xcccccc } - }, - service: { - casing: { width: 7, color: 0x444444 }, - stroke: { width: 5, color: 0xffffff } - }, - special_service: { - casing: { width: 7, color: 0x444444 }, - stroke: { width: 5, color: 0xddccaa } - }, - track: { - casing: { width: 7, color: 0x746f6f }, - stroke: { width: 5, color: 0xc5b59f } - }, - pedestrian: { - casing: { width: 7, color: 0xffffff }, - stroke: { width: 5, color: 0x998888, dash: [8, 8], cap: 'butt' } - }, - path: { - casing: { width: 5, color: 0xddccaa }, - stroke: { width: 3, color: 0x998888, dash: [6, 6], cap: 'butt' } - }, - footway: { - casing: { width: 5, color: 0xffffff }, - stroke: { width: 3, color: 0x998888, dash: [6, 6], cap: 'butt' } - }, - crossing_marked: { - casing: { width: 5, color: 0xddccaa }, - stroke: { width: 3, color: 0x4c4444, dash: [6, 3], cap: 'butt' } - }, - crossing_unmarked: { - casing: { width: 5, color: 0xddccaa }, - stroke: { width: 3, color: 0x776a6a, dash: [6, 4], cap: 'butt' } - }, - cycleway: { - casing: { width: 5, color: 0xffffff }, - stroke: { width: 3, color: 0x58a9ed, dash: [6, 6], cap: 'butt' } - }, - bridleway: { - casing: { width: 5, color: 0xffffff }, - stroke: { width: 3, color: 0xe06d5f, dash: [6, 6], cap: 'butt' } - }, - corridor: { - casing: { width: 5, color: 0xffffff }, - stroke: { width: 3, color: 0x8cd05f, dash: [2, 8], cap: 'round' } - }, - steps: { - casing: { width: 5, color: 0xffffff }, - stroke: { width: 3, color: 0x81d25c, dash: [3, 3], cap: 'butt' } - }, - river: { - fill: { color: 0x77d4de, alpha: 0.3 }, // rgb(119, 211, 222) - casing: { width: 10, color: 0x444444 }, - stroke: { width: 8, color: 0x77dddd } - }, - stream: { - fill: { color: 0x77d4de, alpha: 0.3 }, // rgb(119, 211, 222) - casing: { width: 7, color: 0x444444 }, - stroke: { width: 5, color: 0x77dddd } - }, - ridge: { - stroke: { width: 2, color: 0x8cd05f } // rgb(140, 208, 95) - }, - runway: { - casing: { width: 10, color: 0x000000, cap: 'butt' }, - stroke: { width: 8, color: 0xffffff, dash: [24, 48], cap: 'butt' } - }, - taxiway: { - casing: { width: 7, color: 0x444444 }, - stroke: { width: 5, color: 0xffff00 } - }, - railway: { - casing: { width: 7, color: 0x555555, cap: 'butt' }, - stroke: { width: 2, color: 0xeeeeee, dash: [12, 12], cap: 'butt' } - }, - ferry: { - casing: { alpha: 0 }, // disable - stroke: { width: 3, color: 0x58a9ed, dash: [12, 8], cap: 'butt' } - }, - boundary: { - casing: { width: 6, color: 0x82b5fe, cap: 'butt' }, - stroke: { width: 2, color: 0xffffff, dash: [20, 5, 5, 5], cap: 'butt' } - }, - boundary_park: { - casing: { width: 6, color: 0x82b5fe, cap: 'butt' }, - stroke: { width: 2, color: 0xb0e298, dash: [20, 5, 5, 5], cap: 'butt' } - }, - barrier: { - casing: { alpha: 0 }, // disable - stroke: { width: 3, color: 0xdddddd, dash: [10, 5, 2, 5], cap: 'round' } - }, - barrier_wall: { - casing: { alpha: 0 }, // disable - stroke: { width: 3, color: 0xdddddd, dash: [10, 5, 2, 5], cap: 'round' } - }, - barrier_hedge: { - fill: { color: 0x8cd05f, alpha: 0.3 }, // rgb(140, 208, 95) - casing: { alpha: 0 }, // disable - stroke: { width: 3, color: 0x8cd05f, dash: [10, 5, 2, 5], cap: 'round' } - }, - tree_row: { - casing: { width: 7, color: 0x444444 }, - stroke: { width: 5, color: 0x8cd05f } - }, - construction: { - casing: { width: 10, color: 0xffffff }, - stroke: { width: 8, color: 0xfc6c14, dash: [10, 10], cap: 'butt' } - }, - pipeline: { - casing: { width: 7, color: 0x444444 }, - stroke: { width: 5, color: 0xdddddd, dash: [80, 2], cap: 'butt' } - }, - roller_coaster: { - casing: { width: 7, color: 0x444444 }, - stroke: { width: 5, color: 0xdddddd, dash: [10, 1], cap: 'butt' } - } - }; + this.STYLE_DECLARATIONS = {}; // // A "Style Selector" contains OSM key/value tags to match to a style declaration. @@ -276,17 +118,17 @@ export class StyleSystem extends AbstractSystem { taxiway: 'taxiway' }, amenity: { - childcare: 'yellow', - college: 'yellow', - fountain: 'blue', - kindergarten: 'yellow', - parking: 'darkgray', - research_institute: 'yellow', - school: 'yellow', - university: 'yellow' + childcare: 'common-yellow', + college: 'common-yellow', + fountain: 'common-blue', + kindergarten: 'common-yellow', + parking: 'common-darkgray', + research_institute: 'common-yellow', + school: 'common-yellow', + university: 'common-yellow' }, building: { - '*': 'red' + '*': 'common-red' }, barrier: { city_wall: 'barrier_wall', @@ -308,7 +150,7 @@ export class StyleSystem extends AbstractSystem { '*': 'crossing_unmarked' }, golf: { - green: 'lightgreen' + green: 'common-lightgreen' }, highway: { bridleway: 'bridleway', @@ -342,67 +184,67 @@ export class StyleSystem extends AbstractSystem { unclassified_link: 'unclassified' }, landuse: { - cemetery: 'lightgreen', - commercial: 'orange', - construction: 'gold', - farmland: 'lightgreen', - farmyard: 'tan', - flowerbed: 'green', - forest: 'green', - grass: 'green', - industrial: 'pink', - landfill: 'orange', - meadow: 'lightgreen', - military: 'orange', - orchard: 'lightgreen', - quarry: 'darkgray', - railway: 'darkgray', - recreation_ground: 'green', - residential: 'gold', - retail: 'orange', - village_green: 'green', - vineyard: 'lightgreen' + cemetery: 'common-lightgreen', + commercial: 'common-orange', + construction: 'common-gold', + farmland: 'common-lightgreen', + farmyard: 'common-tan', + flowerbed: 'common-green', + forest: 'common-green', + grass: 'common-green', + industrial: 'common-pink', + landfill: 'common-orange', + meadow: 'common-lightgreen', + military: 'common-orange', + orchard: 'common-lightgreen', + quarry: 'common-darkgray', + railway: 'common-darkgray', + recreation_ground: 'common-green', + residential: 'common-gold', + retail: 'common-orange', + village_green: 'common-green', + vineyard: 'common-lightgreen' }, leisure: { - garden: 'green', - golf_course: 'green', - nature_reserve: 'green', - park: 'green', - pitch: 'green', - swimming_pool: 'blue', - track: 'yellow' + garden: 'common-green', + golf_course: 'common-green', + nature_reserve: 'common-green', + park: 'common-green', + pitch: 'common-green', + swimming_pool: 'common-blue', + track: 'common-yellow' }, man_made: { - adit: 'darkgray', + adit: 'common-darkgray', breakwater: 'barrier_wall', groyne: 'barrier_wall', pipeline: 'pipeline' }, military: { - '*': 'orange' + '*': 'common-orange' }, natural: { - bare_rock: 'darkgray', - bay: 'blue', - beach: 'yellow', - cave_entrance: 'darkgray', - cliff: 'darkgray', - glacier: 'lightgray', + bare_rock: 'common-darkgray', + bay: 'common-blue', + beach: 'common-yellow', + cave_entrance: 'common-darkgray', + cliff: 'common-darkgray', + glacier: 'common-lightgray', ridge: 'ridge', - rock: 'darkgray', - sand: 'yellow', - scree: 'darkgray', - scrub: 'yellow', - shingle: 'darkgray', - stone: 'darkgray', - strait: 'blue', + rock: 'common-darkgray', + sand: 'common-yellow', + scree: 'common-darkgray', + scrub: 'common-yellow', + shingle: 'common-darkgray', + stone: 'common-darkgray', + strait: 'common-blue', tree_row: 'tree_row', - water: 'blue', - wetland: 'teal', - '*': 'green' + water: 'common-blue', + wetland: 'common-teal', + '*': 'common-green' }, power: { - plant: 'pink' + plant: 'common-pink' }, railway: { platform: 'footway', @@ -415,11 +257,11 @@ export class StyleSystem extends AbstractSystem { ferry: 'ferry' }, sport: { - baseball: 'yellow', - basketball: 'darkgray', - beachvolleyball: 'yellow', - skateboard: 'darkgray', - softball: 'yellow' + baseball: 'common-yellow', + basketball: 'common-darkgray', + beachvolleyball: 'common-yellow', + skateboard: 'common-darkgray', + softball: 'common-yellow' }, type: { waterway: 'river' @@ -550,11 +392,11 @@ export class StyleSystem extends AbstractSystem { startAsync() { this._started = true; - // To handle color schemes + // Fetch the color scheme objects from color_schemes.json const context = this.context; const dataloader = context.systems.dataloader; - dataloader.getDataAsync('colors') + dataloader.getDataAsync('color_schemes') .then((data) => { this.colorSchemes = data; // set current scheme to default @@ -563,6 +405,18 @@ export class StyleSystem extends AbstractSystem { this.emit('colorsloaded'); // emit copies }); + // Fetch the style objects from styles.json + dataloader.getDataAsync('styles') + .then((data) => { + this.STYLE_DECLARATIONS = data; + }); + + // Fetch the style objects from styles.json + dataloader.getDataAsync('styles') + .then((data) => { + this.STYLE_DECLARATIONS = data; + }); + return Promise.resolve(); } @@ -632,7 +486,7 @@ export class StyleSystem extends AbstractSystem { if (lifecycleVals.has(v)) score = 999; // exception: lifecycle values if (styleID && score <= styleScore) { - const declaration = this.STYLE_DECLARATIONS[styleID] || colorScheme[styleID]; + const declaration = this.STYLE_DECLARATIONS[styleID]; if (!declaration) { console.error(`invalid styleID: ${styleID}`); // eslint-disable-line continue; @@ -678,14 +532,13 @@ export class StyleSystem extends AbstractSystem { for (const group of ['fill', 'casing', 'stroke']) { style[group] = {}; for (const prop of ['width', 'color', 'alpha', 'cap', 'dash']) { - const value = matched[group] && matched[group][prop]; - if (value !== undefined) { - style[group][prop] = value; - } else { - const fallback = defaults[group] && defaults[group][prop]; - if (fallback !== undefined) { - style[group][prop] = fallback; - } + // Get the style match OR the default if a style match does not exist + const value = matched[group]?.[prop] ?? defaults[group]?.[prop]; + + // Set the property to the fetched value if the fetched value exists + // NOTE: The actual color code has to be fetched from `this.currentColorScheme` + if (value) { + style[group][prop] = (prop !== 'color') ? value : this.currentColorScheme[value.split("-")[0]][value]; } } } diff --git a/scripts/build_data.js b/scripts/build_data.js index 3698a018ce..e64eafc690 100644 --- a/scripts/build_data.js +++ b/scripts/build_data.js @@ -99,7 +99,9 @@ function buildData() { minifySync('data/qa_data.json', 'dist/data/qa_data.min.json'); minifySync('data/shortcuts.json', 'dist/data/shortcuts.min.json'); minifySync('data/territory_languages.json', 'dist/data/territory_languages.min.json'); - minifySync('data/colors.json', 'dist/data/colors.min.json') + minifySync('data/colors.json', 'dist/data/colors.min.json'); + minifySync('data/color_schemes.json', 'dist/data/color_schemes.min.json'); + minifySync('data/styles.json', 'dist/data/styles.min.json'); return _currBuild = Promise.resolve(true) .then(() => { From 51f6814adff2547f4ac6c5c1b4adb766e525b10b Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Tue, 16 Apr 2024 17:04:09 +0100 Subject: [PATCH 04/18] refactor: Remove color grouping in color scheme objects --- data/color_schemes.json | 110 ++++++++++++++++++---------------------- 1 file changed, 49 insertions(+), 61 deletions(-) diff --git a/data/color_schemes.json b/data/color_schemes.json index 83dfdce20c..c58196b313 100644 --- a/data/color_schemes.json +++ b/data/color_schemes.json @@ -1,65 +1,53 @@ { "default": { - "red": { - "red-1": "0xe06e5f", - "red-2": "0xe06d5f", - "red-3": "0xdd2f22", - "red-4": "0x70372f" - }, - "orange": { - "orange-1": "0xf99806", - "orange-2": "0xd6881a", - "orange-3": "0xfc6c14" - }, - "yellow": { - "yellow-1": "0xfff9b3", - "yellow-2": "0xffff94", - "yellow-3": "0xffff00", - "yellow-4": "0xf3f312", - "yellow-5": "0xc4be19" - }, - "green": { - "green-1": "0x99e1aa", - "green-2": "0xb0e298", - "green-3": "0x8cd05f", - "green-4": "0x81d25c", - "green-5": "0xbee83f" - }, - "blue": { - "blue-1": "0x77dddd", - "blue-2": "0x77d4de", - "blue-3": "0x82b5fe", - "blue-4": "0x58a9ed" - }, - "pink": { - "pink-1": "0xe3a4f5", - "pink-2": "0xcf2081" - }, - "brown": { - "brown-1": "0x998888", - "brown-2": "0x776a6a", - "brown-3": "0x746f6f", - "brown-4": "0x4c4444" - }, - "tan": { - "tan-1": "0xf5dcba", - "tan-2": "0xddccaa", - "tan-3": "0xc5b59f" - }, - "white": { - "white-0": "0xffffff" - }, - "black": { - "black-0": "0x000000" - }, - "gray": { - "gray-1": "0xeeeeee", - "gray-2": "0xdddddd", - "gray-3": "0xcccccc", - "gray-4": "0xaaaaaa", - "gray-5": "0x8c8c8c", - "gray-6": "0x555555", - "gray-7": "0x444444" - } + "red-1": "0xe06e5f", + "red-2": "0xe06d5f", + "red-3": "0xdd2f22", + "red-4": "0x70372f", + + "orange-1": "0xf99806", + "orange-2": "0xd6881a", + "orange-3": "0xfc6c14", + + "yellow-1": "0xfff9b3", + "yellow-2": "0xffff94", + "yellow-3": "0xffff00", + "yellow-4": "0xf3f312", + "yellow-5": "0xc4be19", + + "green-1": "0x99e1aa", + "green-2": "0xb0e298", + "green-3": "0x8cd05f", + "green-4": "0x81d25c", + "green-5": "0xbee83f", + + "blue-1": "0x77dddd", + "blue-2": "0x77d4de", + "blue-3": "0x82b5fe", + "blue-4": "0x58a9ed", + + "pink-1": "0xe3a4f5", + "pink-2": "0xcf2081", + + "brown-1": "0x998888", + "brown-2": "0x776a6a", + "brown-3": "0x746f6f", + "brown-4": "0x4c4444", + + "tan-1": "0xf5dcba", + "tan-2": "0xddccaa", + "tan-3": "0xc5b59f", + + "white-0": "0xffffff", + + "black-0": "0x000000", + + "gray-1": "0xeeeeee", + "gray-2": "0xdddddd", + "gray-3": "0xcccccc", + "gray-4": "0xaaaaaa", + "gray-5": "0x8c8c8c", + "gray-6": "0x555555", + "gray-7": "0x444444" } } \ No newline at end of file From 42d2c1d9b625e4a50aa4101508dd7cca4bd443ef Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Tue, 16 Apr 2024 17:05:29 +0100 Subject: [PATCH 05/18] refactor: Update styleMatch() function to use new color system --- data/color_schemes.json | 204 ++++++++++++++++++++++++++++++++++++ data/core.yaml | 6 +- modules/core/StyleSystem.js | 2 +- 3 files changed, 210 insertions(+), 2 deletions(-) diff --git a/data/color_schemes.json b/data/color_schemes.json index c58196b313..a182fec043 100644 --- a/data/color_schemes.json +++ b/data/color_schemes.json @@ -42,6 +42,210 @@ "black-0": "0x000000", + "gray-1": "0xeeeeee", + "gray-2": "0xdddddd", + "gray-3": "0xcccccc", + "gray-4": "0xaaaaaa", + "gray-5": "0x8c8c8c", + "gray-6": "0x555555", + "gray-7": "0x444444" + }, + "ibm": { + "red-1": "0xe06e5f", + "red-2": "0xe06d5f", + "red-3": "0x648fff", + "red-4": "0x785ef0", + + "orange-1": "0xfe6100", + "orange-2": "0xd6881a", + "orange-3": "0xfc6c14", + + "yellow-1": "0xfff9b3", + "yellow-2": "0xffb000", + "yellow-3": "0xffff00", + "yellow-4": "0xf3f312", + "yellow-5": "0xc4be19", + + "green-1": "0x99e1aa", + "green-2": "0xb0e298", + "green-3": "0x8cd05f", + "green-4": "0x81d25c", + "green-5": "0xbee83f", + + "blue-1": "0x77dddd", + "blue-2": "0x77d4de", + "blue-3": "0x82b5fe", + "blue-4": "0x58a9ed", + + "pink-1": "0xe3a4f5", + "pink-2": "0xcf2081", + + "brown-1": "0x998888", + "brown-2": "0x776a6a", + "brown-3": "0x746f6f", + "brown-4": "0x4c4444", + + "tan-1": "0xf5dcba", + "tan-2": "0xddccaa", + "tan-3": "0xc5b59f", + + "white-0": "0xffffff", + + "black-0": "0x000000", + + "gray-1": "0xeeeeee", + "gray-2": "0xdddddd", + "gray-3": "0xcccccc", + "gray-4": "0xaaaaaa", + "gray-5": "0x8c8c8c", + "gray-6": "0x555555", + "gray-7": "0x444444" + }, + "okabe_ito": { + "red-1": "0xcc79a7", + "red-2": "0xe06d5f", + "red-3": "0xd55e00", + "red-4": "0x70372f", + + "orange-1": "0xe69f00", + "orange-2": "0xd6881a", + "orange-3": "0xfc6c14", + + "yellow-1": "0xfff9b3", + "yellow-2": "0xf0e442", + "yellow-3": "0xffff00", + "yellow-4": "0xf3f312", + "yellow-5": "0xc4be19", + + "green-1": "0x99e1aa", + "green-2": "0xb0e298", + "green-3": "0x009e73", + "green-4": "0x81d25c", + "green-5": "0xbee83f", + + "blue-1": "0x77dddd", + "blue-2": "0x56b4e9", + "blue-3": "0x82b5fe", + "blue-4": "0x58a9ed", + + "pink-1": "0xe3a4f5", + "pink-2": "0xcf2081", + + "brown-1": "0x998888", + "brown-2": "0x776a6a", + "brown-3": "0x746f6f", + "brown-4": "0x4c4444", + + "tan-1": "0xf5dcba", + "tan-2": "0xddccaa", + "tan-3": "0xc5b59f", + + "white-0": "0xffffff", + + "black-0": "0x000000", + + "gray-1": "0xeeeeee", + "gray-2": "0xdddddd", + "gray-3": "0xcccccc", + "gray-4": "0xaaaaaa", + "gray-5": "0x8c8c8c", + "gray-6": "0x555555", + "gray-7": "0x444444" + }, + "paul_tol_vibrant": { + "red-1": "0xe06e5f", + "red-2": "0xe06d5f", + "red-3": "0xcc3311", + "red-4": "0xee3377", + + "orange-1": "0xee7733", + "orange-2": "0xd6881a", + "orange-3": "0xfc6c14", + + "yellow-1": "0xfff9b3", + "yellow-2": "0xffff94", + "yellow-3": "0xffff00", + "yellow-4": "0xf3f312", + "yellow-5": "0xc4be19", + + "green-1": "0x99e1aa", + "green-2": "0xb0e298", + "green-3": "0x009988", + "green-4": "0x81d25c", + "green-5": "0xbee83f", + + "blue-1": "0x77dddd", + "blue-2": "0x33bbee", + "blue-3": "0x82b5fe", + "blue-4": "0x58a9ed", + + "pink-1": "0xe3a4f5", + "pink-2": "0xcf2081", + + "brown-1": "0x998888", + "brown-2": "0x776a6a", + "brown-3": "0x746f6f", + "brown-4": "0x4c4444", + + "tan-1": "0xf5dcba", + "tan-2": "0xddccaa", + "tan-3": "0xc5b59f", + + "white-0": "0xffffff", + + "black-0": "0x000000", + + "gray-1": "0xeeeeee", + "gray-2": "0xdddddd", + "gray-3": "0xcccccc", + "gray-4": "0xaaaaaa", + "gray-5": "0x8c8c8c", + "gray-6": "0x555555", + "gray-7": "0x444444" + }, + "paul_tol_muted": { + "red-1": "0xcc6677", + "red-2": "0xe06d5f", + "red-3": "0xaa4499", + "red-4": "0x882255", + + "orange-1": "0xf99806", + "orange-2": "0xd6881a", + "orange-3": "0xfc6c14", + + "yellow-1": "0xfff9b3", + "yellow-2": "0xffff94", + "yellow-3": "0xffff00", + "yellow-4": "0xf3f312", + "yellow-5": "0xc4be19", + + "green-1": "0x99e1aa", + "green-2": "0xb0e298", + "green-3": "0x117733", + "green-4": "0x999933", + "green-5": "0xbee83f", + + "blue-1": "0x44aa99", + "blue-2": "0x88ccee", + "blue-3": "0x82b5fe", + "blue-4": "0x58a9ed", + + "pink-1": "0xe3a4f5", + "pink-2": "0xcf2081", + + "brown-1": "0x998888", + "brown-2": "0x776a6a", + "brown-3": "0x746f6f", + "brown-4": "0x4c4444", + + "tan-1": "0xf5dcba", + "tan-2": "0xddcc77", + "tan-3": "0xc5b59f", + + "white-0": "0xffffff", + + "black-0": "0x000000", + "gray-1": "0xeeeeee", "gray-2": "0xdddddd", "gray-3": "0xcccccc", diff --git a/data/core.yaml b/data/core.yaml index e0c5b98073..ffd283f708 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1002,7 +1002,11 @@ en: title: Map Color Scheme tooltip: Switch between color schemes default: Default - example: Example (High Contrast) + # high_contrast: High Contrast + ibm: IBM + okabe_ito: Okabe-Ito + paul_tol_vibrant: Paul Tol (Vibrant) + paul_tol_muted: Paul Tol (Muted) placeholder: Select color scheme colorblind_options: title: Colorblind Mode diff --git a/modules/core/StyleSystem.js b/modules/core/StyleSystem.js index 4ed16ab8c9..77ce285035 100644 --- a/modules/core/StyleSystem.js +++ b/modules/core/StyleSystem.js @@ -538,7 +538,7 @@ export class StyleSystem extends AbstractSystem { // Set the property to the fetched value if the fetched value exists // NOTE: The actual color code has to be fetched from `this.currentColorScheme` if (value) { - style[group][prop] = (prop !== 'color') ? value : this.currentColorScheme[value.split("-")[0]][value]; + style[group][prop] = (prop !== 'color') ? value : this.currentColorScheme[value]; } } } From 91a22f4d2f2fb2478d1d07d223f4af67f6327ee9 Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Thu, 18 Apr 2024 00:58:25 +0100 Subject: [PATCH 06/18] perf: Add default color scheme handling Add default color scheme property to StyleSystem.js to hold the default color scheme loaded from color_schemes.json. Abstract out HEX color code determination in styleMatch() into its own function, getHexColorCode. Define getHexColorCode() such that it fetches the HEX color code from the default color scheme if it is not defined in the current color scheme to increase efficiency and reduce the amount of information that has to be defined in a new color scheme object. Optimize color scheme definitions in color_schemes.json to utilize the performance upgrade in getHexColorCode() by removing key-value pairs already in the default color scheme. Add another example colorblind-friendly color scheme. Correct spelling mistake in helper function description. --- data/color_schemes.json | 188 +++--------------------------------- data/core.yaml | 1 + modules/core/StyleSystem.js | 33 +++++-- 3 files changed, 36 insertions(+), 186 deletions(-) diff --git a/data/color_schemes.json b/data/color_schemes.json index a182fec043..c16084ba39 100644 --- a/data/color_schemes.json +++ b/data/color_schemes.json @@ -51,207 +51,41 @@ "gray-7": "0x444444" }, "ibm": { - "red-1": "0xe06e5f", - "red-2": "0xe06d5f", "red-3": "0x648fff", "red-4": "0x785ef0", - "orange-1": "0xfe6100", - "orange-2": "0xd6881a", - "orange-3": "0xfc6c14", - - "yellow-1": "0xfff9b3", - "yellow-2": "0xffb000", - "yellow-3": "0xffff00", - "yellow-4": "0xf3f312", - "yellow-5": "0xc4be19", - - "green-1": "0x99e1aa", - "green-2": "0xb0e298", - "green-3": "0x8cd05f", - "green-4": "0x81d25c", - "green-5": "0xbee83f", - - "blue-1": "0x77dddd", - "blue-2": "0x77d4de", - "blue-3": "0x82b5fe", - "blue-4": "0x58a9ed", - - "pink-1": "0xe3a4f5", - "pink-2": "0xcf2081", - - "brown-1": "0x998888", - "brown-2": "0x776a6a", - "brown-3": "0x746f6f", - "brown-4": "0x4c4444", - - "tan-1": "0xf5dcba", - "tan-2": "0xddccaa", - "tan-3": "0xc5b59f", - - "white-0": "0xffffff", - - "black-0": "0x000000", - - "gray-1": "0xeeeeee", - "gray-2": "0xdddddd", - "gray-3": "0xcccccc", - "gray-4": "0xaaaaaa", - "gray-5": "0x8c8c8c", - "gray-6": "0x555555", - "gray-7": "0x444444" + "yellow-2": "0xffb000" }, "okabe_ito": { "red-1": "0xcc79a7", - "red-2": "0xe06d5f", "red-3": "0xd55e00", - "red-4": "0x70372f", - "orange-1": "0xe69f00", - "orange-2": "0xd6881a", - "orange-3": "0xfc6c14", - - "yellow-1": "0xfff9b3", "yellow-2": "0xf0e442", - "yellow-3": "0xffff00", - "yellow-4": "0xf3f312", - "yellow-5": "0xc4be19", - - "green-1": "0x99e1aa", - "green-2": "0xb0e298", "green-3": "0x009e73", - "green-4": "0x81d25c", - "green-5": "0xbee83f", - - "blue-1": "0x77dddd", - "blue-2": "0x56b4e9", - "blue-3": "0x82b5fe", - "blue-4": "0x58a9ed", - - "pink-1": "0xe3a4f5", - "pink-2": "0xcf2081", - - "brown-1": "0x998888", - "brown-2": "0x776a6a", - "brown-3": "0x746f6f", - "brown-4": "0x4c4444", - - "tan-1": "0xf5dcba", - "tan-2": "0xddccaa", - "tan-3": "0xc5b59f", - - "white-0": "0xffffff", - - "black-0": "0x000000", - - "gray-1": "0xeeeeee", - "gray-2": "0xdddddd", - "gray-3": "0xcccccc", - "gray-4": "0xaaaaaa", - "gray-5": "0x8c8c8c", - "gray-6": "0x555555", - "gray-7": "0x444444" + "blue-2": "0x56b4e9" }, "paul_tol_vibrant": { - "red-1": "0xe06e5f", - "red-2": "0xe06d5f", "red-3": "0xcc3311", "red-4": "0xee3377", - "orange-1": "0xee7733", - "orange-2": "0xd6881a", - "orange-3": "0xfc6c14", - - "yellow-1": "0xfff9b3", - "yellow-2": "0xffff94", - "yellow-3": "0xffff00", - "yellow-4": "0xf3f312", - "yellow-5": "0xc4be19", - - "green-1": "0x99e1aa", - "green-2": "0xb0e298", "green-3": "0x009988", - "green-4": "0x81d25c", - "green-5": "0xbee83f", - - "blue-1": "0x77dddd", - "blue-2": "0x33bbee", - "blue-3": "0x82b5fe", - "blue-4": "0x58a9ed", - - "pink-1": "0xe3a4f5", - "pink-2": "0xcf2081", - - "brown-1": "0x998888", - "brown-2": "0x776a6a", - "brown-3": "0x746f6f", - "brown-4": "0x4c4444", - - "tan-1": "0xf5dcba", - "tan-2": "0xddccaa", - "tan-3": "0xc5b59f", - - "white-0": "0xffffff", - - "black-0": "0x000000", - - "gray-1": "0xeeeeee", - "gray-2": "0xdddddd", - "gray-3": "0xcccccc", - "gray-4": "0xaaaaaa", - "gray-5": "0x8c8c8c", - "gray-6": "0x555555", - "gray-7": "0x444444" + "blue-2": "0x33bbee" }, "paul_tol_muted": { "red-1": "0xcc6677", - "red-2": "0xe06d5f", "red-3": "0xaa4499", "red-4": "0x882255", - "orange-1": "0xf99806", - "orange-2": "0xd6881a", - "orange-3": "0xfc6c14", - - "yellow-1": "0xfff9b3", - "yellow-2": "0xffff94", - "yellow-3": "0xffff00", - "yellow-4": "0xf3f312", - "yellow-5": "0xc4be19", - - "green-1": "0x99e1aa", - "green-2": "0xb0e298", "green-3": "0x117733", "green-4": "0x999933", - "green-5": "0xbee83f", - "blue-1": "0x44aa99", - "blue-2": "0x88ccee", - "blue-3": "0x82b5fe", - "blue-4": "0x58a9ed", - - "pink-1": "0xe3a4f5", - "pink-2": "0xcf2081", - - "brown-1": "0x998888", - "brown-2": "0x776a6a", - "brown-3": "0x746f6f", - "brown-4": "0x4c4444", - - "tan-1": "0xf5dcba", - "tan-2": "0xddcc77", - "tan-3": "0xc5b59f", - - "white-0": "0xffffff", - - "black-0": "0x000000", - - "gray-1": "0xeeeeee", - "gray-2": "0xdddddd", - "gray-3": "0xcccccc", - "gray-4": "0xaaaaaa", - "gray-5": "0x8c8c8c", - "gray-6": "0x555555", - "gray-7": "0x444444" + "blue-2": "0x88ccee" + }, + "colorblind_friendly": { + "red-1": "0x530000", + "red-3": "0xcc3311", + "orange-1": "0xfe6100", + "green-3": "0x09f04a", + "green-4": "0x09e04a" } } \ No newline at end of file diff --git a/data/core.yaml b/data/core.yaml index ffd283f708..c6ed72efad 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1007,6 +1007,7 @@ en: okabe_ito: Okabe-Ito paul_tol_vibrant: Paul Tol (Vibrant) paul_tol_muted: Paul Tol (Muted) + colorblind_friendly: Colorblind-Friendly placeholder: Select color scheme colorblind_options: title: Colorblind Mode diff --git a/modules/core/StyleSystem.js b/modules/core/StyleSystem.js index 77ce285035..f979b5ff92 100644 --- a/modules/core/StyleSystem.js +++ b/modules/core/StyleSystem.js @@ -35,9 +35,7 @@ export class StyleSystem extends AbstractSystem { this.context = context; this.dependencies = new Set(['dataloader']); this.autoStart = true; - - // To handle color schemes - this.colorData = null; + this.defaultColorScheme = null; this.colorSchemes = null; this.currentColorScheme = null; @@ -367,6 +365,8 @@ export class StyleSystem extends AbstractSystem { // To handle color schemes this.getColorScheme = this.getColorScheme.bind(this); this.getAllColorSchemes = this.getAllColorSchemes.bind(this); + this.setColorScheme = this.setColorScheme.bind(this); + this.getHexColorCode = this.getHexColorCode.bind(this); } @@ -399,9 +399,9 @@ export class StyleSystem extends AbstractSystem { dataloader.getDataAsync('color_schemes') .then((data) => { this.colorSchemes = data; - // set current scheme to default - this.colorData = data.default; - this.currentColorScheme = 'default'; + // Set the current color scheme to default + this.defaultColorScheme = data.default; + this.currentColorScheme = data.default; this.emit('colorsloaded'); // emit copies }); @@ -439,7 +439,7 @@ export class StyleSystem extends AbstractSystem { } /** - * getAllColorSchemeas + * getAllColorSchemes * @return {Object} All color scheme objects */ getAllColorSchemes() { @@ -459,6 +459,22 @@ export class StyleSystem extends AbstractSystem { } } + /** + * getHexColorCode + * @return {String} HEX color code + */ + getHexColorCode(colorName) { + return this.currentColorScheme[colorName] ?? this.defaultColorScheme[colorName]; + } + + /** + * getHexColorCode + * @return {String} HEX color code + */ + getHexColorCode(colorName) { + return this.currentColorScheme[colorName] ?? this.defaultColorScheme[colorName]; + } + /** * styleMatch * @param {Object} tags - OSM tags to match to a display style @@ -471,7 +487,6 @@ export class StyleSystem extends AbstractSystem { let styleScore = 999; // lower numbers are better let styleKey; // the key controlling the styling, if any let styleVal; // the value controlling the styling, if any - let colorScheme = this.getColorScheme(); // First, match the tags to the best matching `styleID`.. for (const [k, v] of Object.entries(tags)) { @@ -538,7 +553,7 @@ export class StyleSystem extends AbstractSystem { // Set the property to the fetched value if the fetched value exists // NOTE: The actual color code has to be fetched from `this.currentColorScheme` if (value) { - style[group][prop] = (prop !== 'color') ? value : this.currentColorScheme[value]; + style[group][prop] = (prop !== 'color') ? value : this.getHexColorCode(value); } } } From f1dde1c82f2c1fc865382d9d6c553e99a907932f Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Fri, 19 Apr 2024 01:09:40 +0100 Subject: [PATCH 07/18] refactor: update style naming to reflect functionality --- data/styles.json | 24 +++---- modules/core/StyleSystem.js | 122 ++++++++++++++++++------------------ 2 files changed, 73 insertions(+), 73 deletions(-) diff --git a/data/styles.json b/data/styles.json index e5237eeb0c..8fda86f77a 100644 --- a/data/styles.json +++ b/data/styles.json @@ -10,40 +10,40 @@ "stroke": { "dash": [7, 3], "cap": "butt" } }, - "common-red": { + "red-fill": { "fill": { "color": "red-1", "alpha": 0.3 } }, - "common-green": { + "green-fill": { "fill": { "color": "green-3", "alpha": 0.3 } }, - "common-blue": { + "blue-fill": { "fill": { "color": "blue-2", "alpha": 0.3 } }, - "common-yellow": { + "yellow-fill": { "fill": { "color": "yellow-2", "alpha": 0.25 } }, - "common-gold": { + "gold-fill": { "fill": { "color": "yellow-5", "alpha": 0.3 } }, - "common-orange": { + "orange-fill": { "fill": { "color": "orange-2", "alpha": 0.3 } }, - "common-pink": { + "pink-fill": { "fill": { "color": "pink-1", "alpha": 0.3 } }, - "common-teal": { + "teal-fill": { "fill": { "color": "green-1", "alpha": 0.3 } }, - "common-lightgreen": { + "lightgreen-fill": { "fill": { "color": "green-5", "alpha": 0.3 } }, - "common-tan": { + "tan-fill": { "fill": { "color": "tan-1", "alpha": 0.3 } }, - "common-darkgray": { + "darkgray-fill": { "fill": { "color": "gray-6", "alpha": 0.5 } }, - "common-lightgray": { + "lightgray-fill": { "fill": { "color": "gray-7", "alpha": 0.3 } }, diff --git a/modules/core/StyleSystem.js b/modules/core/StyleSystem.js index f979b5ff92..180d3f2afa 100644 --- a/modules/core/StyleSystem.js +++ b/modules/core/StyleSystem.js @@ -116,17 +116,17 @@ export class StyleSystem extends AbstractSystem { taxiway: 'taxiway' }, amenity: { - childcare: 'common-yellow', - college: 'common-yellow', - fountain: 'common-blue', - kindergarten: 'common-yellow', - parking: 'common-darkgray', - research_institute: 'common-yellow', - school: 'common-yellow', - university: 'common-yellow' + childcare: 'yellow-fill', + college: 'yellow-fill', + fountain: 'blue-fill', + kindergarten: 'yellow-fill', + parking: 'darkgray-fill', + research_institute: 'yellow-fill', + school: 'yellow-fill', + university: 'yellow-fill' }, building: { - '*': 'common-red' + '*': 'red-fill' }, barrier: { city_wall: 'barrier_wall', @@ -148,7 +148,7 @@ export class StyleSystem extends AbstractSystem { '*': 'crossing_unmarked' }, golf: { - green: 'common-lightgreen' + green: 'lightgreen-fill' }, highway: { bridleway: 'bridleway', @@ -182,67 +182,67 @@ export class StyleSystem extends AbstractSystem { unclassified_link: 'unclassified' }, landuse: { - cemetery: 'common-lightgreen', - commercial: 'common-orange', - construction: 'common-gold', - farmland: 'common-lightgreen', - farmyard: 'common-tan', - flowerbed: 'common-green', - forest: 'common-green', - grass: 'common-green', - industrial: 'common-pink', - landfill: 'common-orange', - meadow: 'common-lightgreen', - military: 'common-orange', - orchard: 'common-lightgreen', - quarry: 'common-darkgray', - railway: 'common-darkgray', - recreation_ground: 'common-green', - residential: 'common-gold', - retail: 'common-orange', - village_green: 'common-green', - vineyard: 'common-lightgreen' + cemetery: 'lightgreen-fill', + commercial: 'orange-fill', + construction: 'gold-fill', + farmland: 'lightgreen-fill', + farmyard: 'tan-fill', + flowerbed: 'green-fill', + forest: 'green-fill', + grass: 'green-fill', + industrial: 'pink-fill', + landfill: 'orange-fill', + meadow: 'lightgreen-fill', + military: 'orange-fill', + orchard: 'lightgreen-fill', + quarry: 'darkgray-fill', + railway: 'darkgray-fill', + recreation_ground: 'green-fill', + residential: 'gold-fill', + retail: 'orange-fill', + village_green: 'green-fill', + vineyard: 'lightgreen-fill' }, leisure: { - garden: 'common-green', - golf_course: 'common-green', - nature_reserve: 'common-green', - park: 'common-green', - pitch: 'common-green', - swimming_pool: 'common-blue', - track: 'common-yellow' + garden: 'green-fill', + golf_course: 'green-fill', + nature_reserve: 'green-fill', + park: 'green-fill', + pitch: 'green-fill', + swimming_pool: 'blue-fill', + track: 'yellow-fill' }, man_made: { - adit: 'common-darkgray', + adit: 'darkgray-fill', breakwater: 'barrier_wall', groyne: 'barrier_wall', pipeline: 'pipeline' }, military: { - '*': 'common-orange' + '*': 'orange-fill' }, natural: { - bare_rock: 'common-darkgray', - bay: 'common-blue', - beach: 'common-yellow', - cave_entrance: 'common-darkgray', - cliff: 'common-darkgray', - glacier: 'common-lightgray', + bare_rock: 'darkgray-fill', + bay: 'blue-fill', + beach: 'yellow-fill', + cave_entrance: 'darkgray-fill', + cliff: 'darkgray-fill', + glacier: 'lightgray-fill', ridge: 'ridge', - rock: 'common-darkgray', - sand: 'common-yellow', - scree: 'common-darkgray', - scrub: 'common-yellow', - shingle: 'common-darkgray', - stone: 'common-darkgray', - strait: 'common-blue', + rock: 'darkgray-fill', + sand: 'yellow-fill', + scree: 'darkgray-fill', + scrub: 'yellow-fill', + shingle: 'darkgray-fill', + stone: 'darkgray-fill', + strait: 'blue-fill', tree_row: 'tree_row', - water: 'common-blue', - wetland: 'common-teal', - '*': 'common-green' + water: 'blue-fill', + wetland: 'teal-fill', + '*': 'green-fill' }, power: { - plant: 'common-pink' + plant: 'pink-fill' }, railway: { platform: 'footway', @@ -255,11 +255,11 @@ export class StyleSystem extends AbstractSystem { ferry: 'ferry' }, sport: { - baseball: 'common-yellow', - basketball: 'common-darkgray', - beachvolleyball: 'common-yellow', - skateboard: 'common-darkgray', - softball: 'common-yellow' + baseball: 'yellow-fill', + basketball: 'darkgray-fill', + beachvolleyball: 'yellow-fill', + skateboard: 'darkgray-fill', + softball: 'yellow-fill' }, type: { waterway: 'river' From ee9d116d3ba624183d118f052ed9bb3184298741 Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Fri, 19 Apr 2024 02:51:25 +0100 Subject: [PATCH 08/18] feat: Re-implement high-contrast color scheme --- data/color_schemes.json | 20 +++++++++++++++++--- data/core.yaml | 2 +- data/styles.json | 4 ++-- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/data/color_schemes.json b/data/color_schemes.json index c16084ba39..662c8dad01 100644 --- a/data/color_schemes.json +++ b/data/color_schemes.json @@ -5,8 +5,8 @@ "red-3": "0xdd2f22", "red-4": "0x70372f", - "orange-1": "0xf99806", - "orange-2": "0xd6881a", + "orange-1": "0xd6881a", + "orange-2": "0xf99806", "orange-3": "0xfc6c14", "yellow-1": "0xfff9b3", @@ -50,6 +50,20 @@ "gray-6": "0x555555", "gray-7": "0x444444" }, + "high_contrast": { + "red-1": "0xff0e41", + "green-3": "0x09f04a", + "blue-2": "0x0cbcff", + "yellow-2": "0xffca09", + "yellow-5": "0xff0ebc", + "orange-1": "0xff510b", + "pink-1": "0xf1c0e8", + "green-1": "0x12ffd1", + "green-5": "0x540fff", + "tan-1": "0xaffa1f", + "gray-5": "0x0000fe", + "gray-4": "0xe9af1e" + }, "ibm": { "red-3": "0x648fff", "red-4": "0x785ef0", @@ -87,5 +101,5 @@ "orange-1": "0xfe6100", "green-3": "0x09f04a", "green-4": "0x09e04a" - } + } } \ No newline at end of file diff --git a/data/core.yaml b/data/core.yaml index c6ed72efad..a61cf39607 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1002,7 +1002,7 @@ en: title: Map Color Scheme tooltip: Switch between color schemes default: Default - # high_contrast: High Contrast + high_contrast: High Contrast ibm: IBM okabe_ito: Okabe-Ito paul_tol_vibrant: Paul Tol (Vibrant) diff --git a/data/styles.json b/data/styles.json index 8fda86f77a..d752ba6481 100644 --- a/data/styles.json +++ b/data/styles.json @@ -26,7 +26,7 @@ "fill": { "color": "yellow-5", "alpha": 0.3 } }, "orange-fill": { - "fill": { "color": "orange-2", "alpha": 0.3 } + "fill": { "color": "orange-1", "alpha": 0.3 } }, "pink-fill": { "fill": { "color": "pink-1", "alpha": 0.3 } @@ -57,7 +57,7 @@ }, "primary": { "casing": { "width": 10, "color": "red-4" }, - "stroke": { "width": 8, "color": "orange-1" } + "stroke": { "width": 8, "color": "orange-2" } }, "secondary": { "casing": { "width": 10, "color": "red-4" }, From c1d70b36bee52c46b8e095672a979a808637a3f6 Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Fri, 19 Apr 2024 03:00:05 +0100 Subject: [PATCH 09/18] refactor: Remove redundant colors.json file --- data/colors.json | 78 -------------------------------- modules/core/DataLoaderSystem.js | 1 - scripts/build_data.js | 1 - 3 files changed, 80 deletions(-) delete mode 100644 data/colors.json diff --git a/data/colors.json b/data/colors.json deleted file mode 100644 index 6b675aed3a..0000000000 --- a/data/colors.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "default": { - "red": { - "fill": { "color": "0xe06e5f", "alpha": 0.3 } - }, - "green": { - "fill": { "color": "0x8cd05f", "alpha": 0.3 } - }, - "blue": { - "fill": { "color": "0x77d4de", "alpha": 0.3 } - }, - "yellow": { - "fill": { "color": "0xffff94", "alpha": 0.25 } - }, - "gold": { - "fill": { "color": "0xc4be19", "alpha": 0.3 } - }, - "orange": { - "fill": { "color": "0xd6881a", "alpha": 0.3 } - }, - "pink": { - "fill": { "color": "0xe3a4f5", "alpha": 0.3 } - }, - "teal": { - "fill": { "color": "0x99e1aa", "alpha": 0.3 } - }, - "lightgreen": { - "fill": { "color": "0xbee83f", "alpha": 0.3 } - }, - "tan": { - "fill": { "color": "0xf5dcba", "alpha": 0.3 } - }, - "darkgray": { - "fill": { "color": "0x8c8c8c", "alpha": 0.5 } - }, - "lightgray": { - "fill": { "color": "0xaaaaaa", "alpha": 0.3 } - } - }, - "example": { - "red": { - "fill": { "color": "0xFF0E41", "alpha": 0.3 } - }, - "green": { - "fill": { "color": "0x09F04A", "alpha": 0.3 } - }, - "blue": { - "fill": { "color": "0x0CBCFF", "alpha": 0.3 } - }, - "yellow": { - "fill": { "color": "0xFFCA09", "alpha": 0.25 } - }, - "gold": { - "fill": { "color": "0xFF0EBC", "alpha": 0.3 } - }, - "orange": { - "fill": { "color": "0xFF510B", "alpha": 0.3 } - }, - "pink": { - "fill": { "color": "0xF1C0E8", "alpha": 0.3 } - }, - "teal": { - "fill": { "color": "0x12FFD1", "alpha": 0.3 } - }, - "lightgreen": { - "fill": { "color": "0x540FFF", "alpha": 0.3 } - }, - "tan": { - "fill": { "color": "0xAFFA1F", "alpha": 0.3 } - }, - "darkgray": { - "fill": { "color": "0x0000FE", "alpha": 0.5 } - }, - "lightgray": { - "fill": { "color": "0xE9AF1E", "alpha": 0.3 } - } - } -} diff --git a/modules/core/DataLoaderSystem.js b/modules/core/DataLoaderSystem.js index 7eea9765c5..b25a9ff792 100644 --- a/modules/core/DataLoaderSystem.js +++ b/modules/core/DataLoaderSystem.js @@ -24,7 +24,6 @@ export class DataLoaderSystem extends AbstractSystem { const fileMap = new Map(); fileMap.set('address_formats', 'data/address_formats.min.json'); fileMap.set('color_schemes', 'data/color_schemes.min.json'); - fileMap.set('colors', 'data/colors.min.json'); fileMap.set('deprecated', 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@6.6/dist/deprecated.min.json'); fileMap.set('discarded', 'https://cdn.jsdelivr.net/npm/@openstreetmap/id-tagging-schema@6.6/dist/discarded.min.json'); fileMap.set('imagery', 'data/imagery.min.json'); diff --git a/scripts/build_data.js b/scripts/build_data.js index e64eafc690..40e5feb855 100644 --- a/scripts/build_data.js +++ b/scripts/build_data.js @@ -99,7 +99,6 @@ function buildData() { minifySync('data/qa_data.json', 'dist/data/qa_data.min.json'); minifySync('data/shortcuts.json', 'dist/data/shortcuts.min.json'); minifySync('data/territory_languages.json', 'dist/data/territory_languages.min.json'); - minifySync('data/colors.json', 'dist/data/colors.min.json'); minifySync('data/color_schemes.json', 'dist/data/color_schemes.min.json'); minifySync('data/styles.json', 'dist/data/styles.min.json'); From 1cacc049449c71b00e3f9e3e29d2e3d30333bd67 Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Fri, 19 Apr 2024 04:19:01 +0100 Subject: [PATCH 10/18] feat: Finalize three potential colorblind-friendly color schemes --- data/color_schemes.json | 38 ++++++++++---------------------------- data/core.yaml | 8 +++----- 2 files changed, 13 insertions(+), 33 deletions(-) diff --git a/data/color_schemes.json b/data/color_schemes.json index 662c8dad01..10d2514627 100644 --- a/data/color_schemes.json +++ b/data/color_schemes.json @@ -64,42 +64,24 @@ "gray-5": "0x0000fe", "gray-4": "0xe9af1e" }, - "ibm": { + "colorblind_general": { + "red-1": "0x648fff", + "red-3": "0x530000", + "orange-1": "0x179714", + "green-3": "0x09f04a", + "green-4": "0x09e04a" + }, + "colorblind_ibm": { "red-3": "0x648fff", "red-4": "0x785ef0", "orange-1": "0xfe6100", "yellow-2": "0xffb000" }, - "okabe_ito": { - "red-1": "0xcc79a7", - "red-3": "0xd55e00", - "orange-1": "0xe69f00", - "yellow-2": "0xf0e442", - "green-3": "0x009e73", - "blue-2": "0x56b4e9" - }, - "paul_tol_vibrant": { + "colorblind_paul_tol_vibrant": { "red-3": "0xcc3311", "red-4": "0xee3377", "orange-1": "0xee7733", "green-3": "0x009988", "blue-2": "0x33bbee" - }, - "paul_tol_muted": { - "red-1": "0xcc6677", - "red-3": "0xaa4499", - "red-4": "0x882255", - "orange-1": "0xf99806", - "green-3": "0x117733", - "green-4": "0x999933", - "blue-1": "0x44aa99", - "blue-2": "0x88ccee" - }, - "colorblind_friendly": { - "red-1": "0x530000", - "red-3": "0xcc3311", - "orange-1": "0xfe6100", - "green-3": "0x09f04a", - "green-4": "0x09e04a" - } + } } \ No newline at end of file diff --git a/data/core.yaml b/data/core.yaml index a61cf39607..fa2359301d 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1003,11 +1003,9 @@ en: tooltip: Switch between color schemes default: Default high_contrast: High Contrast - ibm: IBM - okabe_ito: Okabe-Ito - paul_tol_vibrant: Paul Tol (Vibrant) - paul_tol_muted: Paul Tol (Muted) - colorblind_friendly: Colorblind-Friendly + colorblind_general: Colorblind Mode - General + colorblind_ibm: Colorblind Mode - IBM + colorblind_paul_tol_vibrant: Colorblind Mode - Paul Tol (Vibrant) placeholder: Select color scheme colorblind_options: title: Colorblind Mode From 0285186c9985bdc5a02efd3ec030a997154fe999 Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Sat, 20 Apr 2024 00:27:11 +0100 Subject: [PATCH 11/18] docs: Add documentation for the proposed color system re-structure --- data/README.md | 194 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 data/README.md diff --git a/data/README.md b/data/README.md new file mode 100644 index 0000000000..608f3e3f01 --- /dev/null +++ b/data/README.md @@ -0,0 +1,194 @@ +# Color-Style System Documentation + +## Rapid Colors + +### Initial Color Approach +As at [Rapid v2.2.5](https://github.com/facebook/Rapid/releases/tag/rapid-v2.2.5), there were four (4) classes of color definition: +1. Colors defined under a name in `StyleSystem.js` +2. Colors defined by direct HEX value in `StyleSystem.js` +3. Colors defined by direct HEX value in `RapidSystem.js` +4. Colors rendered from the map satellite imagery + +Ideally, there would be a central definition of each color which is the same across the Rapid application. +Before diving into the proposed solution to this problem, each class of color definition will be described to provide suitable context. + +#### 1. Named Color Definition +These are the colors defined as parts of key-value pairs in `this.STYLE_DECLATATIONS` object in `/modules/core/StyleSystem.js`, where the key is a named color e.g. 'red', 'blue', 'green' (see the code block below). + +```JS +red: { + fill: { color: 0xe06e5f, alpha: 0.3 } // rgb(224, 110, 95) +} +``` + +There are **12** defined "colors", which are referenced **63** times in total by `this.STYLE_SELECTORS`; this property of the `StyleSystem` class maps feature tags to style declarations (see the code block below). + +```JS +building: { + '*': 'red' +} +``` + +An issue with this particular definition system is that this color definition includes more than just the `color` property (see the first code block in this section). It is also specifies an `alpha` value and is encased in an object which specifies the `fill` property of a map feature. + +#### 2. Direct HEX Color Definition +These colors are also defined as parts of key-value pairs in `this.STYLE_DECLATATIONS` object in `/modules/core/StyleSystem.js`. The difference comes in the nonuse of named colors as keys; rather [OSM tags](https://wiki.openstreetmap.org/wiki/Tags) are used (see the code block below). + +```JS +primary: { + casing: { width: 10, color: 0x70372f }, + stroke: { width: 8, color: 0xf99806 } +} +``` + +There are **30** distinct HEX codes, which are referenced **75** times in total by `this.STYLE_DECLARATIONS` AND the `styleMatch()` function. Usage in `this.STYLE_DECLARATIONS`, as seen in the code block above, is the + +With this color definition system, only the `color` property has anything to do with a color definition; thus, it does not have the same problem definition type #1 has of combining other style definition into color definition. However, there are two issues with the use of direct HEX code usage: +* Due to the repitition of very specific strings, it is error-prone and inefficient for refactoring. +* There are overlaps in the explicitly-defined HEX codes and `color` property values which have already been specified in named color definitions. For instance, the `green.fill.color` is assigned to `0x8cd05f` but this HEX code is also explicitly repeated in five (5) `this.STYLE_DECLARATION` objects such as `amenity: fountain` and `natural: water`. + +#### 3. Rapid Color Definition +The two defintions above cover the colors of *most* of [OpenStreetMap](https://en.wikipedia.org/wiki/OpenStreetMap)'s features - Points, Lines and Areas - which are rendered with [Pixi.js](https://pixijs.com/). Rapid colors are used when rendering Rapid features; these are the AI-generated OpenStreetMap features based on [Facebook Roads](https://github.com/facebookmicrosites/Open-Mapping-At-Facebook) and [Microsoft Buildings](https://github.com/microsoft/GlobalMLBuildingFootprints). + +Rapid colors are strings containing HEX codes which are elements in an array called `RAPID_COLORS`. An issue identified with this particular system is its redundancy; there are **10** Rapid colors but one of them is assigned to a constant again outside the array (specifically, the default Rapid color, `RAPID_MAGENTA`). This will be addressed in the "Future Works" section, as the proposed color system does NOT cover these colors due to the fact that they are already user-defined. + +#### 4. Map Colors +These are the colors which show in the satellite imagery rendered by WebGL which forms the basis of the map. These colors are NOT within the control of Rapid developers but are important to consider when thinking about topics like color vision deficiencies. + + +### Current Color Approach +#### System Aims +1. Centralize all color definitions used within the Rapid codebase +2. Enable efficient and error-resistant HEX code editing +3. Clearly separate color and style definition + +***NOTE**: This color system only takes care of the first two types of colors in Rapid only: named colors and directly-defined colors.* + +#### System Organization +* The colors are grouped by well-known color names such as 'red', 'green' +* There are **11** color groups; these color groups are arranged in ROYGBIV order followed by neutral tones: `brown`, `tan`, `white`, `black` and `grey` +* A color is defined in the format `-` e.g. `red-3`, `blue-4` + * If a color's number is `0`, that means that it is the only one in its group e.g. `white-0`, `black-0` + * For numbers `1` and above, the lower the number, the brighter/paler the color is + +#### (Proposed) Color System + + + + + + + + + +
+ +![#e06e5f](https://placehold.co/20x20/e06e5f/e06e5f.png) `red-1`
+![#e06d5f](https://placehold.co/15x15/e06d5f/e06d5f.png) `red-2`
+![#dd2f22](https://placehold.co/15x15/dd2f22/dd2f22.png) `red-3`
+![#70372f](https://placehold.co/15x15/70372f/70372f.png) `red-4`
+![#d6881a](https://placehold.co/15x15/d6881a/d6881a.png) `orange-1`
+![#f99806](https://placehold.co/15x15/f99806/f99806.png) `orange-2`
+![#fc6c14](https://placehold.co/15x15/fc6c14/fc6c14.png) `orange-3`
+![#fff9b3](https://placehold.co/15x15/fff9b3/fff9b3.png) `yellow-1`
+![#ffff94](https://placehold.co/15x15/ffff94/ffff94.png) `yellow-2`
+![#ffff00](https://placehold.co/15x15/ffff00/ffff00.png) `yellow-3`
+![#f3f312](https://placehold.co/15x15/f3f312/f3f312.png) `yellow-4`
+![#c4be19](https://placehold.co/15x15/c4be19/c4be19.png) `yellow-5`
+![#99e1aa](https://placehold.co/15x15/99e1aa/99e1aa.png) `green-1`
+ +
+ +![#b0e298](https://placehold.co/15x15/b0e298/b0e298.png) `green-2`
+![#8cd05f](https://placehold.co/15x15/8cd05f/8cd05f.png) `green-3`
+![#81d25c](https://placehold.co/15x15/81d25c/81d25c.png) `green-4`
+![#bee83f](https://placehold.co/15x15/bee83f/bee83f.png) `green-5`
+![#77dddd](https://placehold.co/15x15/77dddd/77dddd.png) `blue-1`
+![#77d4de](https://placehold.co/15x15/77d4de/77d4de.png) `blue-2`
+![#82b5fe](https://placehold.co/15x15/82b5fe/82b5fe.png) `blue-3`
+![#58a9ed](https://placehold.co/15x15/58a9ed/58a9ed.png) `blue-4`
+![#e3a4f5](https://placehold.co/15x15/e3a4f5/e3a4f5.png) `pink-1`
+![#cf2081](https://placehold.co/15x15/cf2081/cf2081.png) `pink-2`
+![#998888](https://placehold.co/15x15/998888/998888.png) `brown-1`
+![#776a6a](https://placehold.co/15x15/776a6a/776a6a.png) `brown-2`
+![#746f6f](https://placehold.co/15x15/746f6f/746f6f.png) `brown-3`
+ +
+ + +![#4c4444](https://placehold.co/15x15/4c4444/4c4444.png) `brown-4`
+![#f5dcba](https://placehold.co/15x15/f5dcba/f5dcba.png) `tan-1`
+![#ddccaa](https://placehold.co/15x15/ddccaa/ddccaa.png) `tan-2`
+![#c5b59f](https://placehold.co/15x15/c5b59f/c5b59f.png) `tan-3`
+![#ffffff](https://placehold.co/15x15/ffffff/ffffff.png) `white-0`
+![#000000](https://placehold.co/15x15/000000/000000.png) `black-0`
+![#eeeeee](https://placehold.co/15x15/eeeeee/eeeeee.png) `gray-1`
+![#dddddd](https://placehold.co/15x15/dddddd/dddddd.png) `gray-2`
+![#cccccc](https://placehold.co/15x15/cccccc/cccccc.png) `gray-3`
+![#aaaaaa](https://placehold.co/15x15/aaaaaa/aaaaaa.png) `gray-4`
+![#8c8c8c](https://placehold.co/15x15/8c8c8c/8c8c8c.png) `gray-5`
+![#555555](https://placehold.co/15x15/555555/555555.png) `gray-6`
+![#444444](https://placehold.co/15x15/444444/444444.png) `gray-7`
+ +
+ +#### Relevant Refactoring +To accomodate for the changes to the application, certain things were changed: +1. The `/data/color_schemes.json` file was minified and added to the file system of Rapid in `/scripts/build_data.js` and `/modules/core/DataLoaderSystem.js`, respectively +2. `DataLoaderSystem` is added as a dependency of `StyleSystem` +3. Variables to hold the default color scheme, current color scheme and all color schemes were created and added the the constructor of `StyleSystem` +4. In the `startAsync()` function, `DataLoaderSystem` is used to fetch the color schemes from the `/data/` folder +5. A helper function called `getHexColorCode()` was added to `StyleSystem` to get the HEX color code based on the current color scheme selected. This function is used severally in the `styleMatch()` function +6. All references to colors through named and directly-defined colors in `this.STYLE_DECLARATIONS` were renamed to match the new system + +### Adding New Color Schemes +There are several situations in which a developer may want to change the specific colors used to render features on the map e.g. to ensure colorblind accessibility. The proposed system also takes into consideration the ease with which developers can add a new color scheme. + +1. Identify the specific colors you want to redefine + +2. Identify the new HEX codes you want to assign to each new color + +3. Navigate to `/data/color_schemes.json` + +4. Add a key-value pair for the new color scheme to the document object in the following format: + ``` + "": {} + ``` + ***NOTE**: The convention for this system is to use [snake_case](https://developer.mozilla.org/en-US/docs/Glossary/Snake_case#:~:text=Snake%20case%20is%20a%20way,the%20reader%20of%20its%20appearance.) when naming your new color scheme.* + +5. Add the colors with new definitions (along with said definitions) in key-value pairs to the newly created object in the following format: + ``` + "": "" + ``` + +6. Navigate to `/data/core.yaml` + +7. In the `en` > `preferences` > `color_selection` section, add the name of the color scheme you've just created as well as how you want the color scheme to be named in the Preferences pane dropdown in the following format + ``` + : + ``` + * Ensure that the name you specified in `/data/color_schemes.json` matches the name you refer to it with here + * Ensure that neither `` and `` are NOT surrounded in quotation marks + * ``remember that is case-sensitive + +8. Run `npm run all` jn the terminal to re-build the application with the new color scheme you've just added + +9. Run `npm run quickstart` in the terminal to start the application and look at your new color scheme in action! + + +Here is an example of +```JSON +{ + "colorblind_ibm": { + "red-3": "0x648fff", + "red-4": "0x785ef0", + "orange-1": "0xfe6100", + "yellow-2": "0xffb000" + } +} +``` + +***NOTE**: You will need to rerun `npm run all` anytime you make changes to any file in the `/data/` folder to see the changes in the live application.* + + +## Rapid Styling From ffa9393a0eb17d90bd932aa247d905edc41ee2b5 Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Tue, 23 Apr 2024 22:40:20 +0100 Subject: [PATCH 12/18] docs: Add documentation for the styling system refactor --- data/README.md | 117 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 114 insertions(+), 3 deletions(-) diff --git a/data/README.md b/data/README.md index 608f3e3f01..94578c5680 100644 --- a/data/README.md +++ b/data/README.md @@ -1,4 +1,26 @@ -# Color-Style System Documentation +# Color-Style System Documentation + +**TABLE OF CONTENTS** +- [Rapid Colors](#rapid-colors) + - [Initial Color Approach](#initial-color-approach) + - [1. Named Color Definition](#1-named-color-definition) + - [2. Direct HEX Color Definition](#2-direct-hex-color-definition) + - [3. Rapid Color Definition](#3-rapid-color-definition) + - [4. Map Colors](#4-map-colors) + - [Current Color Approach](#current-color-approach) + - [System Aims](#system-aims) + - [System Organization](#system-organization) + - [(Proposed) Color System](#proposed-color-system) + - [Relevant Refactoring](#relevant-refactoring) + - [Adding New Color Schemes](#adding-new-color-schemes) +- [Rapid Styling](#rapid-styling) + - [Overview](#overview) + - [Instance Variables](#instance-variables) + - [Usage](#usage) + - [Initial vs Current Structure](#initial-vs-current-structure) + - [Relevant Refactoring](#relevant-refactoring-1) +- [Future Possibilities](#future-possibilities) + ## Rapid Colors @@ -135,9 +157,9 @@ These are the colors which show in the satellite imagery rendered by WebGL which #### Relevant Refactoring To accomodate for the changes to the application, certain things were changed: 1. The `/data/color_schemes.json` file was minified and added to the file system of Rapid in `/scripts/build_data.js` and `/modules/core/DataLoaderSystem.js`, respectively -2. `DataLoaderSystem` is added as a dependency of `StyleSystem` +2. `DataLoaderSystem` was added as a dependency of `StyleSystem` 3. Variables to hold the default color scheme, current color scheme and all color schemes were created and added the the constructor of `StyleSystem` -4. In the `startAsync()` function, `DataLoaderSystem` is used to fetch the color schemes from the `/data/` folder +4. In the `startAsync()` function, `DataLoaderSystem` was used to fetch the color schemes from the `/data/` folder 5. A helper function called `getHexColorCode()` was added to `StyleSystem` to get the HEX color code based on the current color scheme selected. This function is used severally in the `styleMatch()` function 6. All references to colors through named and directly-defined colors in `this.STYLE_DECLARATIONS` were renamed to match the new system @@ -192,3 +214,92 @@ Here is an example of ## Rapid Styling +### Overview +Now that we have an understanding of how color is organised, let's zoom out to consider defining feature styling. For future reference, all styling is handled by `StyleSystem.js`, located in the `/modules/core/` folder, regardless of the approach. + +***NOTE**: In this section, we will be assuming the use of the proposed color system, to maintain focus on styling outside of color definition.* + +#### Instance Variables +The `StyleSystem` class has two instance variables in its constructor which are described in comments as follows: +1. `this.STYLE_DECLARATIONS`: A "Style Declaration" contains properties that describe how features should look. Each style declaration has the following structure: + ``` + : { + fill: { }, + casing: { }, + stroke: { } + } + ``` + One or more of three declaration properties - `fill`, `casing` and `stroke` - need to be defined. + +2. `this.STYLE_SELECTORS`: A "Style Selector" contains OSM key/value tags to match to a style declaration. Each style selector has the following structure: + ``` + : { + : styleID + } + ``` + +#### Usage +To illustrate usage, we will use this example of a style declaration and selector, respectively. +```JSON +"residential": { + "casing": { "width": 10, "color": "gray-7" }, + "stroke": { "width": 8, "color": "white-0" } +} +``` +```JS +highway: { + // Other key-value pairs... + residential: 'residential', + residential_link: 'residential' + // Other key-value pairs... +} +``` + +In order for Pixi to render features within the current map extent (see the `render()` function in `/modules/pixi/PixiLayerOsm.js` file), it follows this stripped process: +1. It loads the entities within the current map extent +2. It divides the entities into `polygons`, `lines`, `points` and `vertices` +3. Sub-functions to render each entity type are called e.g. `renderPolygons()` +4. In these sub-functions, the `styleMatch()` function from the `StyleSystem` class is called on the tags of the entity. An example of such a group of tags is as follows: + ```JS + { + // Other feature properties... + tags: { + highway: 'residential', + oneway: 'no' + }, + // Other feature properties... + } + ``` + Let's continue with the OSM tag key `highway` and OSM tag value `residential` +5. The `styleMatch()` function checks if the OSM tag key is in the keys `this.STYLE_SELECTORS` e.g. we can see that `highway` is a part of these keys and `oneway` is not +6. The object which is set to the value of that OSM tag key is fetched and queried for the OSM tag value. In this case, the object assigned to the `highway` key is fetched and then the value of the `residential` key within that object is fetched; in this case, that is `residential`. What we have fetched is the style ID which is defined in `this.STYLE_DECLARATIONS`. Thus, style ID for this use case is set to: + ```JSON + "residential": { + "casing": { "width": 10, "color": "gray-7" }, + "stroke": { "width": 8, "color": "white-0" } + } + ``` +7. We have now successfully connected the OSM tag and value to its assigned style definition! + +There is more to the style matching and rendering process but this is all that is relevant to this explanation. + +### Initial vs Current Structure +Originally, style declarations are defined directly in `StyleSystem.js`. Now, the style declarations have been extracted to a file called `styles.json` which is located in the `/data/` folder. + +This was done with the aim to: +1. Reduce the amount of information in `StyleSystem.js` +2. Abstracting style declaration away from style manipulation + +#### Relevant Refactoring +To accomodate for the changes to the application, certain things were changed: +1. Because the `this.STYLE_DECLARATIONS` now started as a JSON object instead of a JS object, all the keys were surrounded in quotation marks +2. The `/data/styles.json` file was minified and added to the file system of Rapid in `/scripts/build_data.js` and `/modules/core/DataLoaderSystem.js`, respectively +3. The `this.STYLE_DECLARATIONS` variable was initialised to `None` +4. In the `startAsync()` function, `DataLoaderSystem` was used to fetch the style declarations from the `/data/` folder + +## Future Possibilities +1. Consider direct HEX color code usage outside of `this.STYLE_DECLARATIONS` e.g. + * `styleMatch()` in `/modules/core/StyleSystem.js` + * `renderPolygons()` in `/modules/pixi/PixiLayerOsm.js` +2. Incorporate Rapid colors into the color system (as new color entries, NOT a new color scheme) +3. Carry out dedicated research to determine the most intuitive method to order colors \ No newline at end of file From dd711f77717bd41a34d83c2ccb955ee0bcba2745 Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Sat, 27 Apr 2024 19:05:18 +0100 Subject: [PATCH 13/18] feat: Hotkey for color scheme switching (ALT + SHIFT + C) NOTE: Also includes rebasing merge conflict handling --- data/core.yaml | 2 + data/shortcuts.json | 5 ++ modules/core/StyleSystem.js | 52 +++++---------- modules/ui/sections/color_selection.js | 88 +++++++++++++++++--------- 4 files changed, 79 insertions(+), 68 deletions(-) diff --git a/data/core.yaml b/data/core.yaml index fa2359301d..b5472bd77b 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1007,6 +1007,8 @@ en: colorblind_ibm: Colorblind Mode - IBM colorblind_paul_tol_vibrant: Colorblind Mode - Paul Tol (Vibrant) placeholder: Select color scheme + switch_color_scheme: + key: C colorblind_options: title: Colorblind Mode tooltip: Switch between colorblind modes diff --git a/data/shortcuts.json b/data/shortcuts.json index 13e795dcce..02c5f64402 100644 --- a/data/shortcuts.json +++ b/data/shortcuts.json @@ -79,6 +79,11 @@ "shortcuts": ["preferences.key"], "text": "shortcuts.browsing.display_options.preferences" }, + { + "modifiers": ["⌥", "⇧"], + "shortcuts": ["preferences.color_selection.switch_color_scheme.key"], + "text": "shortcuts.browsing.display_options.switch_color_scheme" + }, { "modifiers": ["⌃", "⌘"], "shortcuts": ["F"], diff --git a/modules/core/StyleSystem.js b/modules/core/StyleSystem.js index 180d3f2afa..c7ddc413aa 100644 --- a/modules/core/StyleSystem.js +++ b/modules/core/StyleSystem.js @@ -42,24 +42,24 @@ export class StyleSystem extends AbstractSystem { // Experiment, see Rapid#1230 // matrix values from https://github.com/maputnik/editor this.protanopiaMatrix = [ - 0.567, 0.433, 0, 0, 0, - 0.558, 0.442, 0, 0, 0, - 0, 0.242, 0.758, 0, 0, - 0, 0, 0, 1, 0 + 0.567, 0.433, 0, 0, 0, + 0.558, 0.442, 0, 0, 0, + 0, 0.242, 0.758, 0, 0, + 0, 0, 0, 1, 0 ]; this.deuteranopiaMatrix = [ - 0.625, 0.375, 0, 0, 0, - 0.7, 0.3, 0, 0, 0, - 0, 0.3, 0.7, 0, 0, - 0, 0, 0, 1, 0 + 0.625, 0.375, 0, 0, 0, + 0.7, 0.3, 0, 0, 0, + 0, 0.3, 0.7, 0, 0, + 0, 0, 0, 1, 0 ]; this.tritanopiaMatrix = [ - 0.95, 0.05, 0, 0, 0, - 0, 0.433, 0.567, 0, 0, - 0, 0.475, 0.525, 0, 0, - 0, 0, 0, 1, 0 + 0.95, 0.05, 0, 0, 0, + 0, 0.433, 0.567, 0, 0, + 0, 0.475, 0.525, 0, 0, + 0, 0, 0, 1, 0 ]; @@ -361,8 +361,6 @@ export class StyleSystem extends AbstractSystem { this.styleMatch = this.styleMatch.bind(this); - - // To handle color schemes this.getColorScheme = this.getColorScheme.bind(this); this.getAllColorSchemes = this.getAllColorSchemes.bind(this); this.setColorScheme = this.setColorScheme.bind(this); @@ -411,12 +409,6 @@ export class StyleSystem extends AbstractSystem { this.STYLE_DECLARATIONS = data; }); - // Fetch the style objects from styles.json - dataloader.getDataAsync('styles') - .then((data) => { - this.STYLE_DECLARATIONS = data; - }); - return Promise.resolve(); } @@ -467,14 +459,6 @@ export class StyleSystem extends AbstractSystem { return this.currentColorScheme[colorName] ?? this.defaultColorScheme[colorName]; } - /** - * getHexColorCode - * @return {String} HEX color code - */ - getHexColorCode(colorName) { - return this.currentColorScheme[colorName] ?? this.defaultColorScheme[colorName]; - } - /** * styleMatch * @param {Object} tags - OSM tags to match to a display style @@ -507,7 +491,7 @@ export class StyleSystem extends AbstractSystem { continue; } - matched = declaration || currentScheme; + matched = declaration; styleScore = score; styleKey = k; styleVal = v; @@ -527,17 +511,11 @@ export class StyleSystem extends AbstractSystem { hasLifecycleTag = true; break; - // Lifecycle value, e.g. `railway=demolished` - // (applies only if `k` is styleKey or there is no styleKey controlling styling) + // Lifecycle value, e.g. `railway=demolished` + // (applies only if `k` is styleKey or there is no styleKey controlling styling) } else if ((!styleKey || k === styleKey) && lifecycleVals.has(v)) { hasLifecycleTag = true; break; - - // Lifecycle key prefix, e.g. `demolished:railway=rail` - // (applies only if there is no styleKey controlling the styling) - } else if (!styleKey && lifecycleRegex.test(k) && v !== 'no') { - hasLifecycleTag = true; - break; } } diff --git a/modules/ui/sections/color_selection.js b/modules/ui/sections/color_selection.js index abb9a05374..ee1e0c1ee8 100644 --- a/modules/ui/sections/color_selection.js +++ b/modules/ui/sections/color_selection.js @@ -2,6 +2,7 @@ import { uiTooltip } from '../tooltip.js'; import { uiCombobox } from '../combobox.js'; import { uiSection } from '../section.js'; import { utilNoAuto } from '../../util/index.js'; +import { uiCmd } from '../index.js'; export function uiSectionColorSelection(context) { const l10n = context.systems.l10n; @@ -55,47 +56,72 @@ export function uiSectionColorSelection(context) { .attr('placeholder', l10n.t('preferences.color_selection.placeholder')) .call(utilNoAuto) .call(colorCombo) - .on('blur change', d3_event => { - const element = d3_event.currentTarget; - const val = (element && element.value) || ''; - const data = colorCombo.data(); - if (data.some(item => item.value === val)) { - _colorSelectedId = val; - let colorSchemeName = getColorSchemeName(_colorSelectedId); - - if (styles.currentColorScheme !== colorSchemeName) { - styles.setColorScheme(colorSchemeName); - context.scene().dirtyScene(); - context.systems.map.deferredRedraw(); - } - - } else { - d3_event.currentTarget.value = ''; - _colorSelectedId = null; - } - }); + .on('blur change', d3_event => updateColorScheme(d3_event) ); colorCombo.data(comboData); - update(); + update(selection); - function update() { - selection.selectAll('.preferences-color-selection-item') - .classed('active', (_checkboxState === 'true')) - .select('input') - .property('checked', (_checkboxState === 'true')); + } + + function update(selection) { + selection.selectAll('.preferences-color-selection-item') + .classed('active', (_checkboxState === 'true')) + .select('input') + .property('checked', (_checkboxState === 'true')); + } + + function getColorSchemeName(val) { + for (let i = 0; i < comboData.length; i++) { + let colorSchemeObj = comboData[i]; + if (colorSchemeObj.value === val) { + return colorSchemeObj.title; + } } + } - function getColorSchemeName(val) { - for (let i = 0; i < comboData.length; i++) { - let colorSchemeObj = comboData[i]; - if (colorSchemeObj.value === val) { - return colorSchemeObj.title; - } + function updateColorScheme(d3_event) { + const element = d3_event.currentTarget; + const val = (element && element.value) || ''; + const data = colorCombo.data(); + if (data.some(item => item.value === val)) { + _colorSelectedId = val; + let colorSchemeName = getColorSchemeName(_colorSelectedId); + + if (styles.currentColorScheme !== colorSchemeName) { + styles.setColorScheme(colorSchemeName); + context.scene().dirtyScene(); + context.systems.map.deferredRedraw(); } + + } else { + d3_event.currentTarget.value = ''; + _colorSelectedId = null; } + } + + function switchColorScheme() { + // Get all color schemes + const colorSchemesOrdered = ['default', 'high_contrast', 'colorblind_general', 'colorblind_ibm', 'colorblind_paul_tol_vibrant']; + const allColorSchemes = styles.getAllColorSchemes(); + // Identify the name and index of the current color scheme + const currentColorSchemeName = colorSchemesOrdered.find( item => allColorSchemes[item] == styles.getColorScheme() ); + const currentColorSchemeIndex = colorSchemesOrdered.findIndex( item => item == currentColorSchemeName); + + // Use the index of the current color scheme to identify the next one + const numColorSchemes = Object.keys(styles.getAllColorSchemes()).length; + const nextColorSchemeIndex = (currentColorSchemeIndex + 1) % numColorSchemes; + const nextColorSchemeName = colorSchemesOrdered[nextColorSchemeIndex]; + + // Update the color scheme + styles.setColorScheme(nextColorSchemeName); + context.scene().dirtyScene(); + context.systems.map.deferredRedraw(); } + context.keybinding() + .on(uiCmd('⌥⇧' + l10n.t('preferences.color_selection.switch_color_scheme.key')), switchColorScheme) + return section; } From 468a85121e32a20dc5838db1df564b0ba7b1ff8e Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Tue, 30 Apr 2024 22:39:06 +0100 Subject: [PATCH 14/18] style: Address npm test warnings and errors --- modules/core/StyleSystem.js | 23 ++++--------------- modules/ui/sections/color_selection.js | 6 ++--- .../ui/sections/colorblind_mode_options.js | 2 +- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/modules/core/StyleSystem.js b/modules/core/StyleSystem.js index c7ddc413aa..a24b5c1c53 100644 --- a/modules/core/StyleSystem.js +++ b/modules/core/StyleSystem.js @@ -427,7 +427,7 @@ export class StyleSystem extends AbstractSystem { * @return {Object} Default color scheme object */ getColorScheme() { - return this.colorData; + return this.currentColorScheme; } /** @@ -440,14 +440,14 @@ export class StyleSystem extends AbstractSystem { /** * setColorScheme - * Assigns the colorData var to the new scheme, if the selected scheme is not the current scheme + * Assigns the currentColorScheme var to the new scheme, if the selected scheme is not the current scheme * @param {Object} scheme - color scheme project */ setColorScheme(scheme) { let currentScheme = this.colorSchemes[scheme]; - if (this.colorData !== currentScheme) { + if (this.currentColorScheme !== currentScheme) { this.currentColorScheme = scheme; - this.colorData = currentScheme; + this.currentColorScheme = currentScheme; } } @@ -455,7 +455,7 @@ export class StyleSystem extends AbstractSystem { * getHexColorCode * @return {String} HEX color code */ - getHexColorCode(colorName) { + getHexColorCode(colorName) { return this.currentColorScheme[colorName] ?? this.defaultColorScheme[colorName]; } @@ -624,17 +624,4 @@ export class StyleSystem extends AbstractSystem { return tags[key] === 'no' ? undefined : tags[key]; } } - - // Returns object containing all color scheme objects - getAllColorSchemes() { - return this.STYLE_SCHEMES; - } - - // Sets map color scheme - setColorScheme(schemeName) { - let currentScheme = this.STYLE_SCHEMES[schemeName]; - if (this.currentColorScheme !== currentScheme) { - this.currentColorScheme = currentScheme; - } - } } diff --git a/modules/ui/sections/color_selection.js b/modules/ui/sections/color_selection.js index ee1e0c1ee8..724ed88ad8 100644 --- a/modules/ui/sections/color_selection.js +++ b/modules/ui/sections/color_selection.js @@ -106,8 +106,8 @@ export function uiSectionColorSelection(context) { const allColorSchemes = styles.getAllColorSchemes(); // Identify the name and index of the current color scheme - const currentColorSchemeName = colorSchemesOrdered.find( item => allColorSchemes[item] == styles.getColorScheme() ); - const currentColorSchemeIndex = colorSchemesOrdered.findIndex( item => item == currentColorSchemeName); + const currentColorSchemeName = colorSchemesOrdered.find( item => allColorSchemes[item] === styles.getColorScheme() ); + const currentColorSchemeIndex = colorSchemesOrdered.findIndex( item => item === currentColorSchemeName); // Use the index of the current color scheme to identify the next one const numColorSchemes = Object.keys(styles.getAllColorSchemes()).length; @@ -121,7 +121,7 @@ export function uiSectionColorSelection(context) { } context.keybinding() - .on(uiCmd('⌥⇧' + l10n.t('preferences.color_selection.switch_color_scheme.key')), switchColorScheme) + .on(uiCmd('⌥⇧' + l10n.t('preferences.color_selection.switch_color_scheme.key')), switchColorScheme); return section; } diff --git a/modules/ui/sections/colorblind_mode_options.js b/modules/ui/sections/colorblind_mode_options.js index 6f29b5b7a8..080d4054cb 100644 --- a/modules/ui/sections/colorblind_mode_options.js +++ b/modules/ui/sections/colorblind_mode_options.js @@ -7,7 +7,7 @@ import { utilNoAuto } from '../../util/index.js'; export function uiSectionColorblindModeOptions(context) { const l10n = context.systems.l10n; - const styles = context.systems.styles; + const styles = context.systems.styles; let comboData = [{ title: 'default', value: l10n.t('preferences.colorblind_options.default') }]; From ee35a893a81b824b80d2efdb1d16798c3b5e6b67 Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Wed, 1 May 2024 20:25:52 +0100 Subject: [PATCH 15/18] fix: Remove redundant combo box load function call --- modules/ui/sections/color_selection.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/ui/sections/color_selection.js b/modules/ui/sections/color_selection.js index 724ed88ad8..7f44ca6ed1 100644 --- a/modules/ui/sections/color_selection.js +++ b/modules/ui/sections/color_selection.js @@ -27,8 +27,6 @@ export function uiSectionColorSelection(context) { return comboData; } - comboData = loadComboBoxData(); - const section = uiSection(context, 'preferences-color-selection') .label(l10n.t('preferences.color_selection.title')) .disclosureContent(renderDisclosureContent); From 376336cbaf4072af931771f4920b2839496167cb Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Sat, 4 May 2024 21:15:52 +0100 Subject: [PATCH 16/18] fix: Specify "Help" screen message for color scheme switching hotkey --- data/core.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/data/core.yaml b/data/core.yaml index b5472bd77b..0b21b843e8 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -2554,6 +2554,7 @@ en: map_data: "Toggle map data pane" issues: "Toggle validation issues pane" preferences: "Toggle user preferences pane" + switch_color_scheme: "Switch to next color scheme in list" fullscreen: "Toggle full screen mode" sidebar: "Toggle sidebar" wireframe: "Toggle wireframe mode" From 6d879569ee72cf5ac3e1df2a316cbe561419650a Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Sat, 4 May 2024 21:27:45 +0100 Subject: [PATCH 17/18] refactor: Update Preference panel sub-section text --- data/core.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/data/core.yaml b/data/core.yaml index 0b21b843e8..f9de76855a 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -999,24 +999,24 @@ en: title: Pan the Map tooltip: Scrolling with the wheel will pan the map. Holding down Shift will zoom and unzoom the map. color_selection: - title: Map Color Scheme + title: Color Scheme tooltip: Switch between color schemes default: Default high_contrast: High Contrast - colorblind_general: Colorblind Mode - General - colorblind_ibm: Colorblind Mode - IBM - colorblind_paul_tol_vibrant: Colorblind Mode - Paul Tol (Vibrant) + colorblind_general: Colorblind Palette - General + colorblind_ibm: Colorblind Palette - IBM + colorblind_paul_tol_vibrant: Colorblind Palette - Paul Tol (Vibrant) placeholder: Select color scheme switch_color_scheme: key: C colorblind_options: - title: Colorblind Mode - tooltip: Switch between colorblind modes + title: Colorblind Simulator + tooltip: Switch between colorblind simulators default: Default (None) protanopia: Protanopia deuteranopia: Deuteranopia tritanopia: Tritanopia - placeholder: Select colorblind mode + placeholder: Select colorblind simulator restore: heading: You have unsaved changes description: "Do you wish to restore unsaved changes from a previous editing session?" From dcf234eaa097c63dec73ef5dcc1b00427aca05e2 Mon Sep 17 00:00:00 2001 From: chinweibegbu Date: Tue, 14 May 2024 03:14:32 +0100 Subject: [PATCH 18/18] feat: Make colorblind simulators a poweruser-only feature Add `showColorblindSimulators` to the array of poweruser features. Add strings for the `showColorblindSimulators` feature in the poweruser pop-up to `core.yaml`. Add `_initHide` property to `section.js` to enable initializing any section `
` with a `.hide` class in a non-permanent manner. Call the `initHide()` function with D3.js chaining to set the `_initHide` property of the to `true`, which means that `uiSectionColorblindModeOptions` section should initially be hidden. Add custom on-toggle behavior for `showColorblindSimulators` feature such that the state of the poweruser feature checkbox associated with it adds or removes the `.hide` class from the section's `
`. --- data/core.yaml | 3 +++ modules/ui/rapid_poweruser_features_dialog.js | 12 +++++++++++- modules/ui/section.js | 13 +++++++++++++ modules/ui/sections/colorblind_mode_options.js | 1 + 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/data/core.yaml b/data/core.yaml index f9de76855a..1f4f1358fe 100644 --- a/data/core.yaml +++ b/data/core.yaml @@ -1169,6 +1169,9 @@ en: allowLargeEdits: label: Allow large edits description: Remove the limitations about editing features that are not currently visible + showColorblindSimulators: + label: Enable colorblind simulators + description: Enable the colorblind simulator combo box on the Preference pane for simulating three color vision deficiencies version: whats_new: "What's new in Rapid {version}" tag_reference: diff --git a/modules/ui/rapid_poweruser_features_dialog.js b/modules/ui/rapid_poweruser_features_dialog.js index dee7b72a82..0ca735932f 100644 --- a/modules/ui/rapid_poweruser_features_dialog.js +++ b/modules/ui/rapid_poweruser_features_dialog.js @@ -10,7 +10,7 @@ export function uiRapidPowerUserFeaturesDialog(context) { const urlhash = context.systems.urlhash; const featureFlags = [ - 'previewDatasets', 'tagnosticRoadCombine', 'tagSources', 'showAutoFix', 'allowLargeEdits' + 'previewDatasets', 'tagnosticRoadCombine', 'tagSources', 'showAutoFix', 'allowLargeEdits', 'showColorblindSimulators' ]; let _modalSelection = d3_select(null); @@ -74,6 +74,16 @@ export function uiRapidPowerUserFeaturesDialog(context) { context.enter('browse'); // return to browse mode (in case something was selected) context.systems.map.immediateRedraw(); } + + if (featureFlag === 'showColorblindSimulators') { + let colorblindSimulators = d3_select('.section-preferences-colorblind-mode-options'); + + if (enabled) { + colorblindSimulators.classed('hide', false); + } else { + colorblindSimulators.classed('hide', true); + } + } } diff --git a/modules/ui/section.js b/modules/ui/section.js index f3a4167581..d3feb80005 100644 --- a/modules/ui/section.js +++ b/modules/ui/section.js @@ -13,6 +13,7 @@ export function uiSection(context, sectionID) { let _classes = utilFunctor(''); let _container = d3_select(null); + let _initHide; let _shouldDisplay; let _content; let _disclosure; @@ -40,6 +41,12 @@ export function uiSection(context, sectionID) { return section; }; + section.initHide = function(val) { + if (!arguments.length) return _initHide; + _initHide = utilFunctor(val); + return section; + }; + section.shouldDisplay = function(val) { if (!arguments.length) return _shouldDisplay; _shouldDisplay = utilFunctor(val); @@ -102,6 +109,12 @@ export function uiSection(context, sectionID) { } } + // If there is a _initHide() function, we call it to determine if it should be hidden. + if (typeof _initHide === 'function') { + const initHide = _initHide(); + selection.classed('hide', initHide); + } + // Render the content inside a Disclosure if (_disclosureContent) { if (!_disclosure) { // create if needed diff --git a/modules/ui/sections/colorblind_mode_options.js b/modules/ui/sections/colorblind_mode_options.js index 080d4054cb..7bbe6a7fe8 100644 --- a/modules/ui/sections/colorblind_mode_options.js +++ b/modules/ui/sections/colorblind_mode_options.js @@ -46,6 +46,7 @@ export function uiSectionColorblindModeOptions(context) { const section = uiSection(context, 'preferences-colorblind-mode-options') .label(l10n.t('preferences.colorblind_options.title')) + .initHide(true) .disclosureContent(renderDisclosureContent); const colorblindCombo = uiCombobox(context, 'colorblind-mode-options');