mirror of
https://github.com/DOI-DO/j40-cejst-2.git
synced 2025-02-22 17:44:20 -08:00
Parameterize zoom experiments (#339)
* Adding ability to set flags in url * parameterizing tile layers
This commit is contained in:
parent
6c8d71c5b9
commit
3cd6e06115
6 changed files with 188 additions and 163 deletions
|
@ -25,7 +25,7 @@ const J40Header = () => {
|
||||||
const toggleMobileNav = (): void =>
|
const toggleMobileNav = (): void =>
|
||||||
setMobileNavOpen((prevOpen) => !prevOpen);
|
setMobileNavOpen((prevOpen) => !prevOpen);
|
||||||
|
|
||||||
const headerLinks = (flags: string[] | undefined) => {
|
const headerLinks = (flags: {[key: string] : any} | undefined) => {
|
||||||
// static map of all possible menu items. Originally, it was all strings,
|
// static map of all possible menu items. Originally, it was all strings,
|
||||||
// but we need to handle both onsite and offsite links.
|
// but we need to handle both onsite and offsite links.
|
||||||
const menuData = new Map<string, JSX.Element>([
|
const menuData = new Map<string, JSX.Element>([
|
||||||
|
@ -64,7 +64,7 @@ const J40Header = () => {
|
||||||
// select which items from the above map to show, right now it's only two
|
// select which items from the above map to show, right now it's only two
|
||||||
// possibilities so it's simple. Note: strings are used as react keys
|
// possibilities so it's simple. Note: strings are used as react keys
|
||||||
const menu =
|
const menu =
|
||||||
flags?.includes('sprint3') ?
|
('sprint3' in flags!) ?
|
||||||
['about', 'cejst', 'methodology', 'contact'] :
|
['about', 'cejst', 'methodology', 'contact'] :
|
||||||
['about', 'cejst', 'methodology', 'contact'];
|
['about', 'cejst', 'methodology', 'contact'];
|
||||||
// TODO: make feature flags flags work.
|
// TODO: make feature flags flags work.
|
||||||
|
|
|
@ -7,10 +7,12 @@ import maplibregl, {LngLatBoundsLike,
|
||||||
Popup,
|
Popup,
|
||||||
LngLatLike,
|
LngLatLike,
|
||||||
MapboxGeoJSONFeature} from 'maplibre-gl';
|
MapboxGeoJSONFeature} from 'maplibre-gl';
|
||||||
import mapStyle from '../data/mapStyle';
|
import {makeMapStyle} from '../data/mapStyle';
|
||||||
import PopupContent from './popupContent';
|
import PopupContent from './popupContent';
|
||||||
import * as constants from '../data/constants';
|
import * as constants from '../data/constants';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
|
import {useFlags} from '../contexts/FlagContext';
|
||||||
|
|
||||||
import 'maplibre-gl/dist/maplibre-gl.css';
|
import 'maplibre-gl/dist/maplibre-gl.css';
|
||||||
import * as styles from './J40Map.module.scss';
|
import * as styles from './J40Map.module.scss';
|
||||||
|
|
||||||
|
@ -27,11 +29,12 @@ const J40Map = () => {
|
||||||
const mapRef = useRef<Map>() as React.MutableRefObject<Map>;
|
const mapRef = useRef<Map>() as React.MutableRefObject<Map>;
|
||||||
const selectedFeature = useRef<MapboxGeoJSONFeature>();
|
const selectedFeature = useRef<MapboxGeoJSONFeature>();
|
||||||
const [zoom, setZoom] = useState(constants.GLOBAL_MIN_ZOOM);
|
const [zoom, setZoom] = useState(constants.GLOBAL_MIN_ZOOM);
|
||||||
|
const flags = useFlags();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const initialMap = new Map({
|
const initialMap = new Map({
|
||||||
container: mapContainer.current!,
|
container: mapContainer.current!,
|
||||||
style: mapStyle,
|
style: makeMapStyle(flags),
|
||||||
center: constants.DEFAULT_CENTER as LngLatLike,
|
center: constants.DEFAULT_CENTER as LngLatLike,
|
||||||
zoom: zoom,
|
zoom: zoom,
|
||||||
minZoom: constants.GLOBAL_MIN_ZOOM,
|
minZoom: constants.GLOBAL_MIN_ZOOM,
|
||||||
|
|
|
@ -6,7 +6,7 @@ describe('URL params are parsed and passed to children', () => {
|
||||||
describe('when the URL has a "flags" parameter set', () => {
|
describe('when the URL has a "flags" parameter set', () => {
|
||||||
// We artificially set the URL to localhost?flags=1,2,3
|
// We artificially set the URL to localhost?flags=1,2,3
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
window.history.pushState({}, 'Test Title', '/?flags=1,2,3');
|
window.history.pushState({}, 'Test Title', '/?flags=1,2,3,test=4');
|
||||||
});
|
});
|
||||||
describe('when using useFlags', () => {
|
describe('when using useFlags', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -14,10 +14,11 @@ describe('URL params are parsed and passed to children', () => {
|
||||||
const flags = useFlags();
|
const flags = useFlags();
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div>{flags.includes('1') ? 'yes1' : 'no1'}</div>
|
<div>{'1' in flags ? 'yes1' : 'no1'}</div>
|
||||||
<div>{flags.includes('2') ? 'yes2' : 'no2'}</div>
|
<div>{'2' in flags ? 'yes2' : 'no2'}</div>
|
||||||
<div>{flags.includes('3') ? 'yes3' : 'no3'}</div>
|
<div>{'3' in flags ? 'yes3' : 'no3'}</div>
|
||||||
<div>{flags.includes('4') ? 'yes4' : 'no4'}</div>
|
<div>{'4' in flags ? 'yes4' : 'no4'}</div>
|
||||||
|
<div>{flags['test'] == 4 ? 'yes5' : 'no5'}</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -33,6 +34,7 @@ describe('URL params are parsed and passed to children', () => {
|
||||||
expect(screen.queryByText('yes2')).toBeInTheDocument();
|
expect(screen.queryByText('yes2')).toBeInTheDocument();
|
||||||
expect(screen.queryByText('yes3')).toBeInTheDocument();
|
expect(screen.queryByText('yes3')).toBeInTheDocument();
|
||||||
expect(screen.queryByText('yes4')).not.toBeInTheDocument();
|
expect(screen.queryByText('yes4')).not.toBeInTheDocument();
|
||||||
|
expect(screen.queryByText('yes5')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import * as queryString from 'query-string';
|
import * as queryString from 'query-string';
|
||||||
|
|
||||||
|
export type FlagContainer = { [key: string]: any };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FlagContext stores feature flags and passes them to consumers
|
* FlagContext stores feature flags and passes them to consumers
|
||||||
*/
|
*/
|
||||||
|
@ -8,7 +10,7 @@ import * as queryString from 'query-string';
|
||||||
/**
|
/**
|
||||||
* Contains a list of all currently-active flags
|
* Contains a list of all currently-active flags
|
||||||
*/
|
*/
|
||||||
flags: string[];
|
flags: FlagContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FlagContext = React.createContext<IFlagContext>({flags: []});
|
const FlagContext = React.createContext<IFlagContext>({flags: []});
|
||||||
|
@ -16,9 +18,9 @@ const FlagContext = React.createContext<IFlagContext>({flags: []});
|
||||||
/**
|
/**
|
||||||
* `useFlags` returns all feature flags.
|
* `useFlags` returns all feature flags.
|
||||||
*
|
*
|
||||||
* @return {Flags[]} flags All project feature flags
|
* @return {FlagContainer} flags All project feature flags
|
||||||
*/
|
*/
|
||||||
const useFlags = () : string[] => {
|
const useFlags = () : FlagContainer => {
|
||||||
const {flags} = React.useContext(FlagContext);
|
const {flags} = React.useContext(FlagContext);
|
||||||
return flags;
|
return flags;
|
||||||
};
|
};
|
||||||
|
@ -39,9 +41,18 @@ interface IURLFlagProviderProps {
|
||||||
**/
|
**/
|
||||||
const URLFlagProvider = ({children, location}: IURLFlagProviderProps) => {
|
const URLFlagProvider = ({children, location}: IURLFlagProviderProps) => {
|
||||||
const flagString = queryString.parse(location.search).flags;
|
const flagString = queryString.parse(location.search).flags;
|
||||||
let flags: string[] = [];
|
const flags : FlagContainer = {};
|
||||||
|
let flagList: string[] = [];
|
||||||
if (flagString && typeof flagString === 'string') {
|
if (flagString && typeof flagString === 'string') {
|
||||||
flags = (flagString as string).split(',');
|
flagList = (flagString as string).split(',');
|
||||||
|
}
|
||||||
|
for (const flag of flagList) {
|
||||||
|
if (flag.includes('=')) {
|
||||||
|
const [key, value] = flag.split('=');
|
||||||
|
flags[key] = value;
|
||||||
|
} else {
|
||||||
|
flags[flag] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
console.log(JSON.stringify(location), JSON.stringify(flags));
|
console.log(JSON.stringify(location), JSON.stringify(flags));
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
// URLS
|
// URLS
|
||||||
export const FEATURE_TILE_BASE_URL = 'https://d2zjid6n5ja2pt.cloudfront.net';
|
export const FEATURE_TILE_BASE_URL = 'https://d2zjid6n5ja2pt.cloudfront.net';
|
||||||
const XYZ_SUFFIX = '{z}/{x}/{y}.pbf';
|
const XYZ_SUFFIX = '{z}/{x}/{y}.pbf';
|
||||||
export const FEATURE_TILE_HIGH_ZOOM_URL = `${FEATURE_TILE_BASE_URL}/0629_demo/${XYZ_SUFFIX}`;
|
export const featureURLForTilesetName = (tilesetName :string ) : string => {
|
||||||
export const FEATURE_TILE_LOW_ZOOM_URL = `${FEATURE_TILE_BASE_URL}/tiles_low/${XYZ_SUFFIX}`;
|
return `${FEATURE_TILE_BASE_URL}/${tilesetName}/${XYZ_SUFFIX}`;
|
||||||
|
};
|
||||||
|
export const FEATURE_TILE_HIGH_ZOOM_URL = featureURLForTilesetName('0629_demo');
|
||||||
|
export const FEATURE_TILE_LOW_ZOOM_URL = featureURLForTilesetName('tiles_low');
|
||||||
|
|
||||||
|
|
||||||
// Performance markers
|
// Performance markers
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {Style, FillPaint} from 'maplibre-gl';
|
import {Style, FillPaint} from 'maplibre-gl';
|
||||||
import chroma from 'chroma-js';
|
import chroma from 'chroma-js';
|
||||||
import * as constants from '../data/constants';
|
import * as constants from '../data/constants';
|
||||||
|
import {FlagContainer} from '../contexts/FlagContext';
|
||||||
|
|
||||||
// eslint-disable-next-line require-jsdoc
|
// eslint-disable-next-line require-jsdoc
|
||||||
function hexToHSLA(hex:string, alpha:number) {
|
function hexToHSLA(hex:string, alpha:number) {
|
||||||
|
@ -45,172 +46,177 @@ function makePaint({
|
||||||
|
|
||||||
const imageSuffix = constants.isMobile ? '' : '@2x';
|
const imageSuffix = constants.isMobile ? '' : '@2x';
|
||||||
|
|
||||||
const mapStyle : Style = {
|
export const makeMapStyle = (flagContainer: FlagContainer) : Style => {
|
||||||
'version': 8,
|
return {
|
||||||
'sources': {
|
'version': 8,
|
||||||
'carto': {
|
'sources': {
|
||||||
'type': 'raster',
|
'carto': {
|
||||||
'tiles':
|
'type': 'raster',
|
||||||
|
'tiles':
|
||||||
[
|
[
|
||||||
`https://a.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
`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://b.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||||
`https://c.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`,
|
`https://d.basemaps.cartocdn.com/light_nolabels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||||
],
|
],
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
||||||
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
||||||
},
|
},
|
||||||
'geo': {
|
'geo': {
|
||||||
'type': 'raster',
|
'type': 'raster',
|
||||||
'tiles': [
|
'tiles': [
|
||||||
'https://mt0.google.com/vt/lyrs=p&hl=en&x={x}&y={y}&z={z}',
|
'https://mt0.google.com/vt/lyrs=p&hl=en&x={x}&y={y}&z={z}',
|
||||||
],
|
],
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
||||||
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
||||||
},
|
},
|
||||||
[constants.HIGH_SCORE_SOURCE_NAME]: {
|
[constants.HIGH_SCORE_SOURCE_NAME]: {
|
||||||
// "Score-high" represents the full set of data
|
// "Score-high" represents the full set of data
|
||||||
// at the census block group level. It is only shown
|
// at the census block group level. It is only shown
|
||||||
// at high zoom levels to avoid performance issues at lower zooms
|
// at high zoom levels to avoid performance issues at lower zooms
|
||||||
'type': 'vector',
|
'type': 'vector',
|
||||||
// Our current tippecanoe command does not set an id.
|
// Our current tippecanoe command does not set an id.
|
||||||
// The below line promotes the GEOID10 property to the ID
|
// The below line promotes the GEOID10 property to the ID
|
||||||
'promoteId': constants.GEOID_PROPERTY,
|
'promoteId': constants.GEOID_PROPERTY,
|
||||||
'tiles': [
|
'tiles': [
|
||||||
constants.FEATURE_TILE_HIGH_ZOOM_URL,
|
'high_tiles' in flagContainer ?
|
||||||
],
|
constants.featureURLForTilesetName(flagContainer['high_tiles']) :
|
||||||
// Seeting maxzoom here enables 'overzooming'
|
constants.FEATURE_TILE_HIGH_ZOOM_URL,
|
||||||
// e.g. continued zooming beyond the max bounds.
|
],
|
||||||
// More here: https://docs.mapbox.com/help/glossary/overzoom/
|
// Seeting maxzoom here enables 'overzooming'
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH,
|
// e.g. continued zooming beyond the max bounds.
|
||||||
'maxzoom': constants.GLOBAL_MAX_ZOOM_HIGH,
|
// More here: https://docs.mapbox.com/help/glossary/overzoom/
|
||||||
},
|
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH,
|
||||||
[constants.LOW_SCORE_SOURCE_NAME]: {
|
'maxzoom': constants.GLOBAL_MAX_ZOOM_HIGH,
|
||||||
|
},
|
||||||
|
[constants.LOW_SCORE_SOURCE_NAME]: {
|
||||||
// "Score-low" represents a tileset at the level of bucketed tracts.
|
// "Score-low" represents a tileset at the level of bucketed tracts.
|
||||||
// census block group information is `dissolve`d into tracts, then
|
// census block group information is `dissolve`d into tracts, then
|
||||||
// each tract is `dissolve`d into one of ten buckets. It is meant
|
// each tract is `dissolve`d into one of ten buckets. It is meant
|
||||||
// to give us a favorable tradeoff between performance and fidelity.
|
// to give us a favorable tradeoff between performance and fidelity.
|
||||||
'type': 'vector',
|
'type': 'vector',
|
||||||
'promoteId': constants.GEOID_PROPERTY,
|
'promoteId': constants.GEOID_PROPERTY,
|
||||||
'tiles': [
|
'tiles': [
|
||||||
constants.FEATURE_TILE_LOW_ZOOM_URL,
|
'low_tiles' in flagContainer ?
|
||||||
|
constants.featureURLForTilesetName(flagContainer['low_tiles']) :
|
||||||
|
constants.FEATURE_TILE_LOW_ZOOM_URL,
|
||||||
// For local development, use:
|
// For local development, use:
|
||||||
// 'http://localhost:8080/data/tl_2010_bg_with_data/{z}/{x}/{y}.pbf',
|
// 'http://localhost:8080/data/tl_2010_bg_with_data/{z}/{x}/{y}.pbf',
|
||||||
],
|
],
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM_LOW,
|
'minzoom': constants.GLOBAL_MIN_ZOOM_LOW,
|
||||||
'maxzoom': constants.GLOBAL_MAX_ZOOM_LOW,
|
'maxzoom': constants.GLOBAL_MAX_ZOOM_LOW,
|
||||||
},
|
|
||||||
'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`,
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
'layers': [
|
|
||||||
{
|
|
||||||
'id': 'carto',
|
|
||||||
'source': 'carto',
|
|
||||||
'type': 'raster',
|
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
|
||||||
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'id': 'geo',
|
|
||||||
'source': 'geo',
|
|
||||||
'type': 'raster',
|
|
||||||
'layout': {
|
|
||||||
// Make the layer invisible by default.
|
|
||||||
'visibility': 'none',
|
|
||||||
},
|
},
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
'labels': {
|
||||||
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
'type': 'raster',
|
||||||
},
|
'tiles': [
|
||||||
{
|
`https://cartodb-basemaps-a.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||||
'id': constants.HIGH_SCORE_LAYER_NAME,
|
`https://cartodb-basemaps-b.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||||
'source': constants.HIGH_SCORE_SOURCE_NAME,
|
`https://cartodb-basemaps-c.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||||
'source-layer': constants.SCORE_SOURCE_LAYER,
|
`https://cartodb-basemaps-d.global.ssl.fastly.net/light_only_labels/{z}/{x}/{y}${imageSuffix}.png`,
|
||||||
'type': 'fill',
|
|
||||||
'filter': ['all',
|
|
||||||
['>', constants.SCORE_PROPERTY_HIGH, constants.SCORE_BOUNDARY_THRESHOLD],
|
|
||||||
],
|
|
||||||
'paint': makePaint({
|
|
||||||
field: constants.SCORE_PROPERTY_HIGH,
|
|
||||||
minRamp: constants.SCORE_BOUNDARY_LOW,
|
|
||||||
medRamp: constants.SCORE_BOUNDARY_THRESHOLD,
|
|
||||||
maxRamp: constants.SCORE_BOUNDARY_PRIORITIZED,
|
|
||||||
}),
|
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'id': constants.LOW_SCORE_LAYER_NAME,
|
|
||||||
'source': constants.LOW_SCORE_SOURCE_NAME,
|
|
||||||
'source-layer': constants.SCORE_SOURCE_LAYER,
|
|
||||||
'type': 'fill',
|
|
||||||
'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,
|
|
||||||
}),
|
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM_LOW,
|
|
||||||
'maxzoom': constants.GLOBAL_MAX_ZOOM_LOW,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// "Score-highlights" represents the border
|
|
||||||
// around given tiles that appears at higher zooms
|
|
||||||
'id': 'score-highlights-layer',
|
|
||||||
'source': constants.HIGH_SCORE_SOURCE_NAME,
|
|
||||||
'source-layer': constants.SCORE_SOURCE_LAYER,
|
|
||||||
'type': 'line',
|
|
||||||
'layout': {
|
|
||||||
'visibility': 'visible',
|
|
||||||
'line-join': 'round',
|
|
||||||
'line-cap': 'round',
|
|
||||||
},
|
|
||||||
'paint': {
|
|
||||||
'line-color': constants.DEFAULT_OUTLINE_COLOR,
|
|
||||||
'line-width': 0.8,
|
|
||||||
'line-opacity': 0.5,
|
|
||||||
},
|
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGHLIGHT,
|
|
||||||
'maxzoom': constants.GLOBAL_MAX_ZOOM_HIGHLIGHT,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// "score-border-highlight" is used to highlight
|
|
||||||
// the currently-selected feature
|
|
||||||
'id': 'score-border-highlight-layer',
|
|
||||||
'type': 'line',
|
|
||||||
'source': constants.HIGH_SCORE_SOURCE_NAME,
|
|
||||||
'source-layer': constants.SCORE_SOURCE_LAYER,
|
|
||||||
'layout': {},
|
|
||||||
'paint': {
|
|
||||||
'line-color': constants.BORDER_HIGHLIGHT_COLOR,
|
|
||||||
'line-width': [
|
|
||||||
'case',
|
|
||||||
['boolean', ['feature-state', constants.SELECTED_PROPERTY], false],
|
|
||||||
constants.HIGHLIGHT_BORDER_WIDTH,
|
|
||||||
0,
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH,
|
|
||||||
'maxzoom': constants.GLOBAL_MAX_ZOOM_HIGH,
|
|
||||||
},
|
},
|
||||||
{
|
'layers': [
|
||||||
|
{
|
||||||
|
'id': 'carto',
|
||||||
|
'source': 'carto',
|
||||||
|
'type': 'raster',
|
||||||
|
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
||||||
|
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': 'geo',
|
||||||
|
'source': 'geo',
|
||||||
|
'type': 'raster',
|
||||||
|
'layout': {
|
||||||
|
// Make the layer invisible by default.
|
||||||
|
'visibility': 'none',
|
||||||
|
},
|
||||||
|
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
||||||
|
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': constants.HIGH_SCORE_LAYER_NAME,
|
||||||
|
'source': constants.HIGH_SCORE_SOURCE_NAME,
|
||||||
|
'source-layer': constants.SCORE_SOURCE_LAYER,
|
||||||
|
'type': 'fill',
|
||||||
|
'filter': ['all',
|
||||||
|
['>', constants.SCORE_PROPERTY_HIGH, constants.SCORE_BOUNDARY_THRESHOLD],
|
||||||
|
],
|
||||||
|
'paint': makePaint({
|
||||||
|
field: constants.SCORE_PROPERTY_HIGH,
|
||||||
|
minRamp: constants.SCORE_BOUNDARY_LOW,
|
||||||
|
medRamp: constants.SCORE_BOUNDARY_THRESHOLD,
|
||||||
|
maxRamp: constants.SCORE_BOUNDARY_PRIORITIZED,
|
||||||
|
}),
|
||||||
|
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'id': constants.LOW_SCORE_LAYER_NAME,
|
||||||
|
'source': constants.LOW_SCORE_SOURCE_NAME,
|
||||||
|
'source-layer': constants.SCORE_SOURCE_LAYER,
|
||||||
|
'type': 'fill',
|
||||||
|
'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,
|
||||||
|
}),
|
||||||
|
'minzoom': constants.GLOBAL_MIN_ZOOM_LOW,
|
||||||
|
'maxzoom': constants.GLOBAL_MAX_ZOOM_LOW,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// "Score-highlights" represents the border
|
||||||
|
// around given tiles that appears at higher zooms
|
||||||
|
'id': 'score-highlights-layer',
|
||||||
|
'source': constants.HIGH_SCORE_SOURCE_NAME,
|
||||||
|
'source-layer': constants.SCORE_SOURCE_LAYER,
|
||||||
|
'type': 'line',
|
||||||
|
'layout': {
|
||||||
|
'visibility': 'visible',
|
||||||
|
'line-join': 'round',
|
||||||
|
'line-cap': 'round',
|
||||||
|
},
|
||||||
|
'paint': {
|
||||||
|
'line-color': constants.DEFAULT_OUTLINE_COLOR,
|
||||||
|
'line-width': 0.8,
|
||||||
|
'line-opacity': 0.5,
|
||||||
|
},
|
||||||
|
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGHLIGHT,
|
||||||
|
'maxzoom': constants.GLOBAL_MAX_ZOOM_HIGHLIGHT,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// "score-border-highlight" is used to highlight
|
||||||
|
// the currently-selected feature
|
||||||
|
'id': 'score-border-highlight-layer',
|
||||||
|
'type': 'line',
|
||||||
|
'source': constants.HIGH_SCORE_SOURCE_NAME,
|
||||||
|
'source-layer': constants.SCORE_SOURCE_LAYER,
|
||||||
|
'layout': {},
|
||||||
|
'paint': {
|
||||||
|
'line-color': constants.BORDER_HIGHLIGHT_COLOR,
|
||||||
|
'line-width': [
|
||||||
|
'case',
|
||||||
|
['boolean', ['feature-state', constants.SELECTED_PROPERTY], false],
|
||||||
|
constants.HIGHLIGHT_BORDER_WIDTH,
|
||||||
|
0,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'minzoom': constants.GLOBAL_MIN_ZOOM_HIGH,
|
||||||
|
'maxzoom': constants.GLOBAL_MAX_ZOOM_HIGH,
|
||||||
|
},
|
||||||
|
{
|
||||||
// We put labels last to ensure prominence
|
// We put labels last to ensure prominence
|
||||||
'id': 'labels-only-layer',
|
'id': 'labels-only-layer',
|
||||||
'type': 'raster',
|
'type': 'raster',
|
||||||
'source': 'labels',
|
'source': 'labels',
|
||||||
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
'minzoom': constants.GLOBAL_MIN_ZOOM,
|
||||||
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
'maxzoom': constants.GLOBAL_MAX_ZOOM,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default mapStyle;
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue