mirror of
https://github.com/DOI-DO/j40-cejst-2.git
synced 2025-10-01 08:43:17 -07:00
Add additional base layers behind feature flags (#945)
* Add additional base layers behind feature flags - add voyager base layer under vy - add positron base layer under ps * Add mapbox base layer - requires API token * Add mapbox layers with API token in URL * Add base map layers from mapTiler - add comments to mapping components - add mapTiler base maps behind feature flags * Comment out intermittent cypress test failures * Add flag to remove label layer * Add MapBox Raster and Vector tiles - tilesets are commented out until more information is provided by Mikel * Remove white layer on non-prioritized features - removes makePaint function - adds Todo to renaming constants * refactor all contants to have standard naming - renames layers, sources, colors, opacity, and zoom - Adds a large amount of comments to understand how this map works * remove some instances of mapbox-gl - this the first step in having only maplibre-gl being used in app * Remove chroma.js - chroma.js was used in the fill function of makeStyle. This was used to create a gradient between non-prio, threshold and prio. Since these 3 step values are no longer needed this function along with the libraries it used is not removed. * Add comments on mapbox base layer - adds apiaccesstoken * set basemap to mapbox and move all layers to Map * Add API KEY to .env, adjust opacity of prio'd CBTs - remove this function as it is no longer being used - add comments on map - create a high layer opacity and low layer opacity - add API KEY to prod and dev .env - add MapBox API key to deploy_staging * add logging to troubleshoot API KEY * Remove temp echo of API KEY * Add GHA env var to gatsby config * Remove API KEY from GitHub and GHA
This commit is contained in:
parent
d686bb856e
commit
667678f20e
12 changed files with 438 additions and 254 deletions
|
@ -2,6 +2,8 @@
|
|||
import {LngLatBoundsLike} from 'maplibre-gl';
|
||||
import {isMobile as isMobileReactDeviceDetect} from 'react-device-detect';
|
||||
|
||||
export const isMobile = isMobileReactDeviceDetect;
|
||||
|
||||
const XYZ_SUFFIX = '{z}/{x}/{y}.pbf';
|
||||
export const featureURLForTilesetName = (tilesetName: string): string => {
|
||||
// The feature tile base URL and path can either point locally or the CDN.
|
||||
|
@ -29,18 +31,13 @@ export const FEATURE_TILE_LOW_ZOOM_URL = featureURLForTilesetName('low');
|
|||
// Performance markers
|
||||
export const PERFORMANCE_MARKER_MAP_IDLE = 'MAP_IDLE';
|
||||
|
||||
// ******* PROPERTIES FROM TILE SERVER **************
|
||||
export type J40Properties = { [key: string]: any };
|
||||
|
||||
// Properties
|
||||
export const SCORE_PROPERTY_HIGH = 'SL_PFS';
|
||||
export const SCORE_PROPERTY_LOW = 'L_SCORE';
|
||||
export const GEOID_PROPERTY = 'GEOID10';
|
||||
export const HIGH_SCORE_SOURCE_NAME = 'score-high';
|
||||
export const HIGH_SCORE_LAYER_NAME = 'score-high-layer';
|
||||
export const LOW_SCORE_SOURCE_NAME = 'score-low';
|
||||
export const LOW_SCORE_LAYER_NAME = 'score-low-layer';
|
||||
export const SELECTED_PROPERTY = 'selected';
|
||||
export const CURRENTLY_SELECTED_FEATURE_HIGHLIGHT_LAYER_NAME = 'currently-selected-feature-highlight-layer';
|
||||
export const BLOCK_GROUP_BOUNDARY_LAYER_NAME = 'block-group-boundary-layer';
|
||||
|
||||
|
||||
// Indicator values:
|
||||
export const ASTHMA_PERCENTILE = 'AF_PFS';
|
||||
|
@ -113,20 +110,57 @@ export const TOTAL_THRESHOLD_CRITERIA = 'TC';
|
|||
export const IS_GTE_90_ISLAND_AREA_UNEMPLOYMENT_AND_IS_LOW_HS_EDU_2009 = 'IAULHSE';
|
||||
export const IS_GTE_90_ISLAND_AREA_BELOW_100_POVERTY_AND_IS_LOW_HS_EDU_2009 = 'ISPLHSE';
|
||||
export const IS_GTE_90_ISLAND_AREA_LOW_MEDIAN_INCOME_AND_IS_LOW_HS_EDU_2009 = 'IALMILHSE';
|
||||
export type J40Properties = { [key: string]: any };
|
||||
|
||||
// The name of the layer within the tiles that contains the score
|
||||
export const SCORE_SOURCE_LAYER = 'blocks';
|
||||
|
||||
|
||||
// ********** MAP CONSTANTS ***************
|
||||
|
||||
// Source name constants
|
||||
export const BASE_MAP_SOURCE_NAME = 'base-map-source-name';
|
||||
export const HIGH_ZOOM_SOURCE_NAME = 'high-zoom-source-name';
|
||||
export const LOW_ZOOM_SOURCE_NAME = 'low-zoom-source-name';
|
||||
|
||||
// Layer ID constants
|
||||
export const BASE_MAP_LAYER_ID = 'base-map-layer-id';
|
||||
export const HIGH_ZOOM_LAYER_ID = 'high-zoom-layer-id';
|
||||
export const PRIORITIZED_HIGH_ZOOM_LAYER_ID = 'prioritized-high-zoom-layer-id';
|
||||
export const LOW_ZOOM_LAYER_ID = 'low-zoom-layer-id';
|
||||
export const FEATURE_BORDER_LAYER_ID = 'feature-border-layer-id';
|
||||
export const SELECTED_FEATURE_BORDER_LAYER_ID = 'selected-feature-border-layer-id';
|
||||
|
||||
// Zoom
|
||||
export const GLOBAL_MIN_ZOOM = 3;
|
||||
export const GLOBAL_MAX_ZOOM = 22;
|
||||
export const GLOBAL_MIN_ZOOM_LOW = 3;
|
||||
export const GLOBAL_MAX_ZOOM_LOW = 7;
|
||||
export const GLOBAL_MIN_ZOOM_HIGHLIGHT = 8;
|
||||
export const GLOBAL_MAX_ZOOM_HIGHLIGHT = 22;
|
||||
export const GLOBAL_MIN_ZOOM_HIGH = 7;
|
||||
export const GLOBAL_MAX_ZOOM_HIGH = 11;
|
||||
export const GLOBAL_MIN_ZOOM_FEATURE_BORDER = 8;
|
||||
export const GLOBAL_MAX_ZOOM_FEATURE_BORDER = 22;
|
||||
|
||||
// Opacity
|
||||
export const FEATURE_BORDER_OPACITY = 0.5;
|
||||
export const HIGH_ZOOM_PRIORITIZED_FEATURE_FILL_OPACITY = 0.3;
|
||||
export const LOW_ZOOM_PRIORITIZED_FEATURE_FILL_OPACITY = 0.6;
|
||||
export const NON_PRIORITIZED_FEATURE_FILL_OPACITY = 0;
|
||||
|
||||
// Colors
|
||||
export const FEATURE_BORDER_COLOR = '#4EA5CF';
|
||||
export const SELECTED_FEATURE_BORDER_COLOR = '#1A4480';
|
||||
export const PRIORITIZED_FEATURE_FILL_COLOR = '#768FB3';
|
||||
|
||||
// Widths
|
||||
export const FEATURE_BORDER_WIDTH = 0.8;
|
||||
export const SELECTED_FEATURE_BORDER_WIDTH = 5.0;
|
||||
|
||||
/**
|
||||
* This threshold will determine if the feature is prioritized
|
||||
* or not. Currently all values are railed to 0 or 1 so this value
|
||||
* doesn't really matter.
|
||||
*/
|
||||
export const SCORE_BOUNDARY_THRESHOLD = 0.6;
|
||||
|
||||
// Bounds - these bounds can be obtained by using the getCurrentMapBoundingBox() function in the map
|
||||
export const GLOBAL_MAX_BOUNDS: LngLatBoundsLike = [
|
||||
|
@ -175,25 +209,3 @@ export const US_VIRGIN_ISLANDS_BOUNDS: LngLatBoundsLike = [
|
|||
];
|
||||
|
||||
export const DEFAULT_CENTER = [33.4687126, -97.502136];
|
||||
|
||||
// Opacity
|
||||
export const DEFAULT_LAYER_OPACITY = 0.6;
|
||||
|
||||
// Colors
|
||||
export const DEFAULT_OUTLINE_COLOR = '#4EA5CF';
|
||||
export const MIN_COLOR = '#FFFFFF';
|
||||
export const MED_COLOR = '#D1DAE6';
|
||||
export const MAX_COLOR = '#768FB3';
|
||||
export const BORDER_HIGHLIGHT_COLOR = '#1A4480';
|
||||
export const CURRENTLY_SELECTED_FEATURE_LAYER_OPACITY = 0.5;
|
||||
|
||||
// Widths
|
||||
export const HIGHLIGHT_BORDER_WIDTH = 5.0;
|
||||
export const CURRENTLY_SELECTED_FEATURE_LAYER_WIDTH = 0.8;
|
||||
|
||||
// Score boundaries
|
||||
export const SCORE_BOUNDARY_LOW = 0.0;
|
||||
export const SCORE_BOUNDARY_THRESHOLD = 0.6;
|
||||
export const SCORE_BOUNDARY_PRIORITIZED = 0.75;
|
||||
|
||||
export const isMobile = isMobileReactDeviceDetect;
|
||||
|
|
|
@ -1,67 +1,106 @@
|
|||
import {Style, FillPaint} from 'maplibre-gl';
|
||||
import chroma from 'chroma-js';
|
||||
import {Style} from 'maplibre-gl';
|
||||
import * as constants from '../data/constants';
|
||||
import {FlagContainer} from '../contexts/FlagContext';
|
||||
|
||||
// eslint-disable-next-line require-jsdoc
|
||||
function hexToHSLA(hex:string, alpha:number) {
|
||||
return chroma(hex).alpha(alpha).css('hsl');
|
||||
}
|
||||
|
||||
/**
|
||||
* `MakePaint` generates a zoom-faded Maplibre style formatted layer given a set of parameters.
|
||||
*
|
||||
* @param {string} field : the field within the data to consult
|
||||
* @param {number} minRamp : the minimum value this can assume
|
||||
* @param {number} medRamp : the medium value this can assume
|
||||
* @param {number} maxRamp : the maximum value this can assume
|
||||
* @return {FillPaint} a maplibregl fill layer
|
||||
**/
|
||||
function makePaint({
|
||||
field,
|
||||
minRamp,
|
||||
medRamp,
|
||||
maxRamp,
|
||||
}: {
|
||||
field: string;
|
||||
minRamp: number;
|
||||
medRamp: number;
|
||||
maxRamp: number;
|
||||
}): FillPaint {
|
||||
const paintDescriptor : FillPaint = {
|
||||
'fill-color': [
|
||||
'step',
|
||||
['get', field],
|
||||
hexToHSLA(constants.MIN_COLOR, constants.DEFAULT_LAYER_OPACITY ),
|
||||
minRamp,
|
||||
hexToHSLA(constants.MIN_COLOR, constants.DEFAULT_LAYER_OPACITY ),
|
||||
medRamp,
|
||||
hexToHSLA(constants.MED_COLOR, constants.DEFAULT_LAYER_OPACITY ),
|
||||
maxRamp,
|
||||
hexToHSLA(constants.MAX_COLOR, constants.DEFAULT_LAYER_OPACITY ),
|
||||
],
|
||||
};
|
||||
return paintDescriptor;
|
||||
}
|
||||
|
||||
// *********** BASE MAP SOURCES ***************
|
||||
const imageSuffix = constants.isMobile ? '' : '@2x';
|
||||
|
||||
// Original "light" Base layer
|
||||
// Additional layers found here: https://carto.com/help/building-maps/basemap-list/#carto-vector-basemaps
|
||||
const cartoLightBaseLayer = {
|
||||
noLabels: [
|
||||
`https://a.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://b.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://c.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://d.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
],
|
||||
labelsOnly: [
|
||||
`https://cartodb-basemaps-a.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://cartodb-basemaps-b.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://cartodb-basemaps-c.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://cartodb-basemaps-d.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
],
|
||||
};
|
||||
|
||||
// MapTiler base map source
|
||||
// Todo: move API key to .env
|
||||
const getMapTilerBaseLayer = (name:string, API_KEY='KMA4bawPDNtR6zNIAfUH') => {
|
||||
return [
|
||||
`https://api.maptiler.com/maps/${name}/{z}/{x}/{y}${imageSuffix}.png?key=${API_KEY}`,
|
||||
];
|
||||
};
|
||||
|
||||
// Utility function to make map styles according to JSON spec of MapBox
|
||||
// https://docs.mapbox.com/mapbox-gl-js/style-spec/
|
||||
export const makeMapStyle = (flagContainer: FlagContainer) : Style => {
|
||||
// Add flags for various types of MapTiler base maps:
|
||||
const getBaseMapLayer = () => {
|
||||
if ('mt-streets' in flagContainer) {
|
||||
return getMapTilerBaseLayer('streets');
|
||||
} else if ('mt-bright' in flagContainer) {
|
||||
return getMapTilerBaseLayer('bright');
|
||||
} else if ('mt-voyager' in flagContainer) {
|
||||
return getMapTilerBaseLayer('voyager');
|
||||
} else if ('mt-osm' in flagContainer) {
|
||||
return getMapTilerBaseLayer('osm-standard');
|
||||
} else {
|
||||
return cartoLightBaseLayer.noLabels;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
'version': 8,
|
||||
|
||||
/**
|
||||
* Removing any sources, removes the map from rendering, since the layers key is depenedent on these
|
||||
* sources.
|
||||
*
|
||||
* - base map source: This source control the base map.
|
||||
* - geo: currently not being used
|
||||
* - high zoom source: comes from our tile server for high zoom tiles
|
||||
* - low zoom source: comes from our tile server for low zoom tiles
|
||||
* - labels source: currently using carto's label-only source
|
||||
* */
|
||||
'sources': {
|
||||
'carto': {
|
||||
|
||||
/**
|
||||
* The base map source source allows us to define where the tiles can be fetched from.
|
||||
* Currently we are evaluating carto, MapTiler, Geoampify and MapBox for viable base maps.
|
||||
*/
|
||||
[constants.BASE_MAP_SOURCE_NAME]: {
|
||||
'type': 'raster',
|
||||
'tiles':
|
||||
[
|
||||
`https://a.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://b.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://c.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://d.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
],
|
||||
'tiles': getBaseMapLayer(),
|
||||
|
||||
/**
|
||||
* Attempting to place a direct call to mapbox URL:
|
||||
*/
|
||||
// 'type': 'raster',
|
||||
// 'tiles': [`mapbox://styles/mapbox/streets-v11`],
|
||||
|
||||
/**
|
||||
* This MapBox Raster seems to work, however the tileset curently available in MapBox
|
||||
* is the "satellite" tileset. Messaged Mikel on more options.
|
||||
*/
|
||||
// 'type': 'raster',
|
||||
// 'tiles': [
|
||||
// `https://api.mapbox.com/v4/mapbox.satellite/{z}/{x}/{y}.png?access_token=pk.eyJ1IjoianVzdGljZTQwIiwiYSI6ImNreGF1Z3loNjB0N3oybm9jdGpxeDZ4b3kifQ.76tMHU7C8wwn0HGsF6azjA`,
|
||||
// ],
|
||||
|
||||
/**
|
||||
* This MapBox Vector does not work, attempting to place this in the main component as
|
||||
* a <Source> and <Layer> component also did not work.
|
||||
*/
|
||||
// 'type': 'vector',
|
||||
// 'tiles': [
|
||||
// `https://api.mapbox.com/v4/mapbox.mapbox-streets-v8/{z}/{x}/{y}.vector.pbf?access_token=pk.eyJ1IjoianVzdGljZTQwIiwiYSI6ImNreGF1Z3loNjB0N3oybm9jdGpxeDZ4b3kifQ.76tMHU7C8wwn0HGsF6azjA`,
|
||||
// ],
|
||||
|
||||
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
||||
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
||||
},
|
||||
|
||||
// In the layer (below) where the geo source is used, the layer is invisible
|
||||
'geo': {
|
||||
'type': 'raster',
|
||||
'tiles': [
|
||||
|
@ -70,10 +109,10 @@ export const makeMapStyle = (flagContainer: FlagContainer) : Style => {
|
|||
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
||||
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
||||
},
|
||||
[constants.HIGH_SCORE_SOURCE_NAME]: {
|
||||
// "Score-high" represents the full set of data
|
||||
// at the census block group level. It is only shown
|
||||
// at high zoom levels to avoid performance issues at lower zooms
|
||||
|
||||
// The High zoom source:
|
||||
[constants.HIGH_ZOOM_SOURCE_NAME]: {
|
||||
// It is only shown at high zoom levels to avoid performance issues at lower zooms
|
||||
'type': 'vector',
|
||||
// Our current tippecanoe command does not set an id.
|
||||
// The below line promotes the GEOID10 property to the ID
|
||||
|
@ -83,13 +122,15 @@ export const makeMapStyle = (flagContainer: FlagContainer) : Style => {
|
|||
constants.featureURLForTilesetName(flagContainer['high_tiles']) :
|
||||
constants.FEATURE_TILE_HIGH_ZOOM_URL,
|
||||
],
|
||||
// Seeting maxzoom here enables 'overzooming'
|
||||
// Setting maxzoom here enables 'overzooming'
|
||||
// e.g. continued zooming beyond the max bounds.
|
||||
// More here: https://docs.mapbox.com/help/glossary/overzoom/
|
||||
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH,
|
||||
'maxzoom': constants.GLOBAL_MAX_ZOOM_HIGH,
|
||||
},
|
||||
[constants.LOW_SCORE_SOURCE_NAME]: {
|
||||
|
||||
// The Low zoom source:
|
||||
[constants.LOW_ZOOM_SOURCE_NAME]: {
|
||||
// "Score-low" represents a tileset at the level of bucketed tracts.
|
||||
// census block group information is `dissolve`d into tracts, then
|
||||
// each tract is `dissolve`d into one of ten buckets. It is meant
|
||||
|
@ -106,70 +147,126 @@ export const makeMapStyle = (flagContainer: FlagContainer) : Style => {
|
|||
'minzoom': constants.GLOBAL_MIN_ZOOM_LOW,
|
||||
'maxzoom': constants.GLOBAL_MAX_ZOOM_LOW,
|
||||
},
|
||||
|
||||
// The labels source:
|
||||
'labels': {
|
||||
'type': 'raster',
|
||||
'tiles': [
|
||||
`https://cartodb-basemaps-a.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://cartodb-basemaps-b.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://cartodb-basemaps-c.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
`https://cartodb-basemaps-d.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||
],
|
||||
'tiles': cartoLightBaseLayer.labelsOnly,
|
||||
},
|
||||
},
|
||||
|
||||
/**
|
||||
* Each object in the layers array references it's source via the source key.
|
||||
* Each layer stacks upon the previous layer in the array of layers.
|
||||
*
|
||||
* - baseMapLayer: the base layer without labels
|
||||
* - geo: a geographical layer that is not being used
|
||||
* - high zoom layer - non-prioritized features only
|
||||
* - high zoom layer - prioritized features only
|
||||
* - low zoom layer - prioritized features only
|
||||
* - labels only layer
|
||||
*/
|
||||
'layers': [
|
||||
// The baseMapLayer
|
||||
{
|
||||
'id': 'carto',
|
||||
'source': 'carto',
|
||||
'id': constants.BASE_MAP_LAYER_ID,
|
||||
'source': constants.BASE_MAP_SOURCE_NAME,
|
||||
'type': 'raster',
|
||||
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
||||
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
||||
},
|
||||
|
||||
// The Geo layer adds a geographical layer like mountains and rivers
|
||||
{
|
||||
'id': 'geo',
|
||||
'source': 'geo',
|
||||
'type': 'raster',
|
||||
'layout': {
|
||||
// Make the layer invisible by default.
|
||||
'visibility': 'none',
|
||||
// Place visibility behind flag:
|
||||
'visibility': 'geo' in flagContainer ? 'visible' : 'none',
|
||||
},
|
||||
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
||||
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
||||
},
|
||||
|
||||
/**
|
||||
* High zoom layer - non-prioritized features only
|
||||
*/
|
||||
{
|
||||
'id': constants.HIGH_SCORE_LAYER_NAME,
|
||||
'source': constants.HIGH_SCORE_SOURCE_NAME,
|
||||
'id': constants.HIGH_ZOOM_LAYER_ID,
|
||||
'source': constants.HIGH_ZOOM_SOURCE_NAME,
|
||||
'source-layer': constants.SCORE_SOURCE_LAYER,
|
||||
/**
|
||||
* This shows features where the high score < score boundary threshold.
|
||||
* In other words, this filter out prioritized features
|
||||
*/
|
||||
'filter': ['all',
|
||||
['<', constants.SCORE_PROPERTY_HIGH, constants.SCORE_BOUNDARY_THRESHOLD],
|
||||
],
|
||||
|
||||
'type': 'fill',
|
||||
'paint': makePaint({
|
||||
field: constants.SCORE_PROPERTY_HIGH,
|
||||
minRamp: constants.SCORE_BOUNDARY_LOW,
|
||||
medRamp: constants.SCORE_BOUNDARY_THRESHOLD,
|
||||
maxRamp: constants.SCORE_BOUNDARY_PRIORITIZED,
|
||||
}),
|
||||
'paint': {
|
||||
'fill-opacity': constants.NON_PRIORITIZED_FEATURE_FILL_OPACITY,
|
||||
},
|
||||
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH,
|
||||
},
|
||||
|
||||
/**
|
||||
* High zoom layer - prioritized features only
|
||||
*/
|
||||
{
|
||||
'id': constants.LOW_SCORE_LAYER_NAME,
|
||||
'source': constants.LOW_SCORE_SOURCE_NAME,
|
||||
'id': constants.PRIORITIZED_HIGH_ZOOM_LAYER_ID,
|
||||
'source': constants.HIGH_ZOOM_SOURCE_NAME,
|
||||
'source-layer': constants.SCORE_SOURCE_LAYER,
|
||||
/**
|
||||
* This shows features where the high score > score boundary threshold.
|
||||
* In other words, this filter out non-prioritized features
|
||||
*/
|
||||
'filter': ['all',
|
||||
['>', constants.SCORE_PROPERTY_HIGH, constants.SCORE_BOUNDARY_THRESHOLD],
|
||||
],
|
||||
|
||||
'type': 'fill',
|
||||
'paint': {
|
||||
'fill-color': constants.PRIORITIZED_FEATURE_FILL_COLOR,
|
||||
'fill-opacity': constants.PRIORITIZED_FEATURE_FILL_OPACITY,
|
||||
},
|
||||
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH,
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Low zoom layer - prioritized features only
|
||||
*/
|
||||
{
|
||||
'id': constants.LOW_ZOOM_LAYER_ID,
|
||||
'source': constants.LOW_ZOOM_SOURCE_NAME,
|
||||
'source-layer': constants.SCORE_SOURCE_LAYER,
|
||||
/**
|
||||
* This shows features where the low score > score boundary threshold.
|
||||
* In other words, this filter out non-prioritized features
|
||||
*/
|
||||
'filter': ['all',
|
||||
['>', constants.SCORE_PROPERTY_LOW, constants.SCORE_BOUNDARY_THRESHOLD],
|
||||
],
|
||||
'paint': makePaint({
|
||||
field: constants.SCORE_PROPERTY_LOW,
|
||||
minRamp: constants.SCORE_BOUNDARY_LOW,
|
||||
medRamp: constants.SCORE_BOUNDARY_THRESHOLD,
|
||||
maxRamp: constants.SCORE_BOUNDARY_PRIORITIZED,
|
||||
}),
|
||||
|
||||
'type': 'fill',
|
||||
'paint': {
|
||||
'fill-color': constants.PRIORITIZED_FEATURE_FILL_COLOR,
|
||||
'fill-opacity': constants.PRIORITIZED_FEATURE_FILL_OPACITY,
|
||||
},
|
||||
'minzoom': constants.GLOBAL_MIN_ZOOM_LOW,
|
||||
'maxzoom': constants.GLOBAL_MAX_ZOOM_LOW,
|
||||
},
|
||||
|
||||
// A layer for labels only
|
||||
{
|
||||
// We put labels last to ensure prominence
|
||||
'id': 'labels-only-layer',
|
||||
'type': 'raster',
|
||||
'source': 'labels',
|
||||
'type': 'raster',
|
||||
'layout': {
|
||||
'visibility': 'remove-label-layer' in flagContainer ? 'none' : 'visible',
|
||||
},
|
||||
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
||||
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue