Skip to content

Commit

Permalink
Carto: fetchMap to support custom basemaps
Browse files Browse the repository at this point in the history
  • Loading branch information
zbigg committed Apr 30, 2024
1 parent 65f9a25 commit e683c7b
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 8 deletions.
73 changes: 73 additions & 0 deletions modules/carto/src/api/basemap-style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import {KeplerMapConfig} from './types';

const getRasterJsonMapStyle = (url: string) => ({
version: 8,
sources: {
'basemap-tile-source': {
type: 'raster',
tiles: [url],
tileSize: 256
}
},
layers: [
{
id: 'basemap-tiles',
type: 'raster',
source: 'basemap-tile-source',
minzoom: 0,
maxzoom: 22
}
]
});

function isRasterBasemap(url: string) {
return /.*(?=.*\{z\})(?=.*\{x\})(?=.*\{y\}).*/.test(url);
}

function isTileJsonBasemap(url: string) {
return /.*(.json)/.test(url) && !url.includes('service=WMS');
}

function isWmtsBasemap(url: string) {
return url.includes('service=WMS');
}

export function getCustomBasemapStyle(url: string): string | any {
if (isRasterBasemap(url)) {
return getRasterJsonMapStyle(url);
} else if (isTileJsonBasemap(url)) {
return url;
} else if (isWmtsBasemap(url)) {
return getRasterJsonMapStyle(url);
}
throw new Error('Unknown basemap format');
}

const CARTO_MAP_BASEURL = 'https://basemaps.cartocdn.com/gl/';
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 getCartoMapStyle(config: KeplerMapConfig) {
const {mapStyle} = config;
const styleType = mapStyle.styleType || 'positron';
if (styleType.startsWith('custom:')) {
const currentCustomBasemap = config.customBaseMaps?.custom;
if (currentCustomBasemap) {
return {
styleUrl: getCustomBasemapStyle(currentCustomBasemap.settings.url),
attribution: currentCustomBasemap.attribution
};
}
}
if (CARTO_MAP_STYLES.includes(styleType)) {
const {label} = mapStyle.visibleLayerGroups;
const labelSuffix = label ? '' : '-nolabels';
const styleUrl = `${CARTO_MAP_BASEURL}${mapStyle.styleType}${labelSuffix}-gl-style/style.json`;
return {
styleUrl,
attribution: CARTO_MAP_ATRRIBUTION
};
}
return null;
}
6 changes: 4 additions & 2 deletions modules/carto/src/api/parse-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ import {
import PointLabelLayer from '../layers/point-label-layer';
import {CollisionFilterExtension} from '@deck.gl/extensions';
import {assert} from '../utils';
import {MapDataset, MapLayerConfig, VisualChannels} from './types';
import {KeplerMapConfig, MapDataset, MapLayerConfig, VisualChannels} from './types';
import {getCartoMapStyle} from './basemap-style';

const collisionFilterExtension = new CollisionFilterExtension();

export function parseMap(json) {
const {keplerMapConfig, datasets, token} = json;
assert(keplerMapConfig.version === 'v1', 'Only support Kepler v1');
const {mapState, mapStyle} = keplerMapConfig.config;
const {mapState, mapStyle} = keplerMapConfig.config as KeplerMapConfig;
const {layers, layerBlending, interactionConfig} = keplerMapConfig.config.visState;

return {
Expand All @@ -34,6 +35,7 @@ export function parseMap(json) {
updatedAt: json.updatedAt,
initialViewState: mapState,
mapStyle,
basemap: getCartoMapStyle(keplerMapConfig.config),
token,
layers: layers.reverse().map(({id, type, config, visualChannels}) => {
try {
Expand Down
27 changes: 27 additions & 0 deletions modules/carto/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,3 +176,30 @@ export type MapDataset = {
aggregationResLevel: number | null;
geoColumn: string;
};

export interface Basemap {
id: string;
name: string;

settings: {
url: string;
};
type: 'wmts' | 'raster' | 'tilejson';
thumbnail: string;
attribution?: string;
}
export type KeplerMapConfig = {
mapState: any;
mapStyle: {
styleType: string;
visibleLayerGroups: Record<string, boolean>;
};
visState: {
layers: MapConfigLayer[];
};
layerBlending: any;
interactionConfig: any;
customBaseMaps?: {
custom?: Basemap;
};
};
12 changes: 6 additions & 6 deletions test/apps/carto-map/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ async function createMap(cartoMapId: string) {
}

// Get map info from CARTO and update deck
const {initialViewState, mapStyle, layers} = await fetchMap(options);
const {initialViewState, mapStyle, basemap, layers} = await fetchMap(options);
deck.setProps({initialViewState, layers});

// Mapbox basemap (optional)
const {label} = mapStyle.visibleLayerGroups;
const MAP_STYLE = `https://basemaps.cartocdn.com/gl/${mapStyle.styleType}${
label ? '' : '-nolabels'
}-gl-style/style.json`;
const map = new mapboxgl.Map({container: 'map', style: MAP_STYLE, interactive: false});
// const {label} = mapStyle.visibleLayerGroups;
// const MAP_STYLE = `https://basemaps.cartocdn.com/gl/${mapStyle.styleType}${
// label ? '' : '-nolabels'
// }-gl-style/style.json`;
const map = new mapboxgl.Map({container: 'map', style: basemap?.styleUrl, interactive: false});
deck.setProps({
controller: true,
onViewStateChange: ({viewState}) => {
Expand Down

0 comments on commit e683c7b

Please sign in to comment.