Skip to content

Commit

Permalink
support visibleLayerGroups in carto styles
Browse files Browse the repository at this point in the history
  • Loading branch information
zbigg committed May 6, 2024
1 parent 173c2a4 commit 4972f03
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 10 deletions.
42 changes: 36 additions & 6 deletions modules/carto/src/api/basemap.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import {cartoBasemapsBaseUrl} from '../basemap';
import {cartoBasemapsBaseUrl, cartoStyleLayerGroups} from '../basemap';
import {KeplerMapConfig} from './types';

const DEFAULT_CARTO_STYLE = 'positron';
const CARTO_MAP_STYLES = ['positron', 'dark-matter', 'voyager'];
const CARTO_MAP_ATRRIBUTION = `© <a href="https://carto.com/about-carto/" target="_blank" rel="noopener noreferrer">CARTO</a>, ©
<a href="http://www.openstreetmap.org/copyright" target="_blank" rel="noopener noreferrer">OpenStreetMap</a> contributors`;

export function getBasemapSettings(config: KeplerMapConfig) {
export function applyLayerGroupFilters(style, visibleLayerGroups) {
const visibleFilters = cartoStyleLayerGroups
.filter(lg => visibleLayerGroups[lg.slug])
.map(lg => lg.filter);

const filteredLayers = style.layers.filter(layer => visibleFilters.some(match => match(layer)));

return {
...style,
layers: filteredLayers
};
}

export async function getBasemap(config: KeplerMapConfig) {
/* global fetch */
const {mapStyle} = config;
const styleType = mapStyle.styleType || DEFAULT_CARTO_STYLE;
if (styleType.startsWith('custom:')) {
Expand All @@ -19,11 +33,27 @@ export function getBasemapSettings(config: KeplerMapConfig) {
}
}
if (CARTO_MAP_STYLES.includes(styleType)) {
const {label} = mapStyle.visibleLayerGroups;
const labelSuffix = label ? '' : '-nolabels';
const styleUrl = `${cartoBasemapsBaseUrl}${styleType}${labelSuffix}-gl-style/style.json`;
const {visibleLayerGroups} = mapStyle;
const styleUrl = `${cartoBasemapsBaseUrl}/${styleType}-gl-style/style.json`;
let style = styleUrl;

if (mapStyle.visibleLayerGroups) {
try {
const originalStyle = await fetch(styleUrl, {
mode: 'cors',
credentials: 'omit'
}).then(async res => res.json());
style = applyLayerGroupFilters(originalStyle, visibleLayerGroups);
} catch (error) {
// eslint-disable-next-line no-console
console.error(
'Error fetching CARTO basemap style, falling back to not-filtered style',
error
);
}
}
return {
style: styleUrl,
style,
attribution: CARTO_MAP_ATRRIBUTION
};
}
Expand Down
8 changes: 6 additions & 2 deletions modules/carto/src/api/fetch-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {parseMap} from './parse-map';
import {requestWithParameters} from './request-with-parameters';
import {assert} from '../utils';
import type {APIErrorContext, Format, MapType, QueryParameters} from './types';
import {getBasemap} from './basemap';

type Dataset = {
id: string;
Expand Down Expand Up @@ -276,8 +277,11 @@ export async function fetchMap({
await fillInMapDatasets(map, clientId, apiBaseUrl, headers);

// Mutates attributes in visualChannels to contain tile stats
await fillInTileStats(map, apiBaseUrl);
const out = {...parseMap(map), ...{stopAutoRefresh}};
const [basemap] = await Promise.all([
getBasemap(map.keplerMapConfig.config, errorContext),

Check failure on line 281 in modules/carto/src/api/fetch-map.ts

View workflow job for this annotation

GitHub Actions / test-python (3.8)

Expected 1 arguments, but got 2.

Check failure on line 281 in modules/carto/src/api/fetch-map.ts

View workflow job for this annotation

GitHub Actions / test-node

Expected 1 arguments, but got 2.
fillInTileStats(map, apiBaseUrl)
]);
const out = {...parseMap(map), basemap, ...{stopAutoRefresh}};

const textLayers = out.layers.filter(layer => {
const pointType = layer.props.pointType || '';
Expand Down
2 changes: 0 additions & 2 deletions modules/carto/src/api/parse-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import PointLabelLayer from '../layers/point-label-layer';
import {CollisionFilterExtension} from '@deck.gl/extensions';
import {assert} from '../utils';
import {KeplerMapConfig, MapDataset, MapLayerConfig, VisualChannels} from './types';
import {getBasemapSettings} from './basemap';

const collisionFilterExtension = new CollisionFilterExtension();

Expand All @@ -35,7 +34,6 @@ export function parseMap(json) {
updatedAt: json.updatedAt,
initialViewState: mapState,
mapStyle,
basemap: getBasemapSettings(keplerMapConfig.config),
token,
layers: layers.reverse().map(({id, type, config, visualChannels}) => {
try {
Expand Down
38 changes: 38 additions & 0 deletions modules/carto/src/basemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,44 @@ export const cartoBasemapsBaseUrl = 'https://basemaps.cartocdn.com/gl';

const baseUrl = `${cartoBasemapsBaseUrl}/{basemap}-gl-style/style.json`;

export const cartoStyleLayerGroups = [
{
slug: 'label',
filter: ({id}: {id: string}) =>
Boolean(
id.match(/(?=(label|_label|place-|place_|poi-|poi_|watername_|roadname_|housenumber))/)
),
defaultVisibility: true
},
{
slug: 'road',
filter: ({id}: {id: string}) =>
Boolean(id.match(/(?=(road|railway|tunnel|street|bridge))(?!.*label)/)),
defaultVisibility: true
},
{
slug: 'border',
filter: ({id}: {id: string}) => Boolean(id.match(/border|boundaries|boundary_/)),
defaultVisibility: false
},
{
slug: 'building',
filter: ({id}: {id: string}) => Boolean(id.match(/building/)),
defaultVisibility: true
},
{
slug: 'water',
filter: ({id}: {id: string}) => Boolean(id.match(/(?=(water|stream|ferry))/)),
defaultVisibility: true
},
{
slug: 'land',
filter: ({id}: {id: string}) =>
Boolean(id.match(/(?=(parks|landcover|industrial|sand|hillshade|park_))/)),
defaultVisibility: true
}
];

export default {
VOYAGER: baseUrl.replace('{basemap}', 'voyager'),
POSITRON: baseUrl.replace('{basemap}', 'positron'),
Expand Down

0 comments on commit 4972f03

Please sign in to comment.