Skip to content

Commit

Permalink
CARTO: Support styling layer by color column (#8177)
Browse files Browse the repository at this point in the history
  • Loading branch information
Josmorsot authored and felixpalmer committed Oct 24, 2023
1 parent 4c11ce5 commit 157b988
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 27 deletions.
63 changes: 37 additions & 26 deletions modules/carto/src/api/layer-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import H3TileLayer from '../layers/h3-tile-layer';
import QuadbinTileLayer from '../layers/quadbin-tile-layer';
import RasterTileLayer from '../layers/raster-tile-layer';
import {MapType, TILE_FORMATS, TileFormat} from './maps-api-common';
import {assert, createBinaryProxy} from '../utils';
import {assert, createBinaryProxy, scaleIdentity} from '../utils';
import {
CustomMarkersRange,
MapDataset,
Expand All @@ -41,7 +41,8 @@ const SCALE_FUNCS = {
quantile: scaleQuantile,
quantize: scaleQuantize,
sqrt: scaleSqrt,
custom: scaleThreshold
custom: scaleThreshold,
identity: scaleIdentity
};
export type SCALE_TYPE = keyof typeof SCALE_FUNCS;

Expand Down Expand Up @@ -317,7 +318,7 @@ export function opacityToAlpha(opacity?: number) {
return opacity !== undefined ? Math.round(255 * Math.pow(opacity, 1 / 2.2)) : 255;
}

function getAccessorKeys(name: string, aggregation: string | undefined): string[] {
function getAccessorKeys(name: string, aggregation?: string | undefined): string[] {
let keys = [name];
if (aggregation) {
// Snowflake will capitalized the keys, need to check lower and upper case version
Expand All @@ -343,33 +344,13 @@ export function getColorValueAccessor({name}, colorAggregation, data: any) {
}

export function getColorAccessor(
{name},
{name, colorColumn}: VisualChannelField,
scaleType: SCALE_TYPE,
{aggregation, range: {colors, colorMap}},
{aggregation, range},
opacity: number | undefined,
data: any
) {
const scale = SCALE_FUNCS[scaleType as any]();
let domain: (string | number)[] = [];
let scaleColor: string[] = [];

if (Array.isArray(colorMap)) {
colorMap.forEach(([value, color]) => {
domain.push(value);
scaleColor.push(color);
});
} else {
domain = calculateDomain(data, name, scaleType, colors.length);
scaleColor = colors;
}

if (scaleType === 'ordinal') {
domain = domain.slice(0, scaleColor.length);
}

scale.domain(domain);
scale.range(scaleColor);
scale.unknown(UNKNOWN_COLOR);
const scale = calculateLayerScale(colorColumn || name, scaleType, range, data);
const alpha = opacityToAlpha(opacity);

let accessorKeys = getAccessorKeys(name, aggregation);
Expand All @@ -384,6 +365,36 @@ export function getColorAccessor(
return normalizeAccessor(accessor, data);
}

function calculateLayerScale(name, scaleType, range, data) {
const scale = SCALE_FUNCS[scaleType]();
let domain: (string | number)[] = [];
let scaleColor: string[] = [];

if (scaleType !== 'identity') {
const {colorMap, colors} = range;

if (Array.isArray(colorMap)) {
colorMap.forEach(([value, color]) => {
domain.push(value);
scaleColor.push(color);
});
} else {
domain = calculateDomain(data, name, scaleType, colors.length);
scaleColor = colors;
}

if (scaleType === 'ordinal') {
domain = domain.slice(0, scaleColor.length);
}
}

scale.domain(domain);
scale.range(scaleColor);
scale.unknown(UNKNOWN_COLOR);

return scale;
}

const FALLBACK_ICON =
'data:image/svg+xml;charset=utf-8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iNTAiLz4NCjwvc3ZnPg==';

Expand Down
1 change: 1 addition & 0 deletions modules/carto/src/api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {SCALE_TYPE} from './layer-map';
export type VisualChannelField = {
name: string;
type: string;
colorColumn?: string;
};

export type VisualChannels = {
Expand Down
24 changes: 24 additions & 0 deletions modules/carto/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,27 @@ export function getWorkerUrl(id: string, version: string) {
// return `http://localhost:8081/dist/${id}-worker.js`;
return `https://unpkg.com/@deck.gl/carto@${version}/dist/${id}-worker.js`;
}

export function scaleIdentity() {
let unknown;

function scale(x) {
return x === null ? unknown : x;
}

scale.invert = scale;

scale.domain = scale.range = d => d;

scale.unknown = u => {
if (u) {
unknown = u;
}

return unknown;
};

scale.copy = () => scaleIdentity().unknown(unknown);

return scale;
}
3 changes: 2 additions & 1 deletion test/apps/carto-map/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@ const examples = [
'12119dd2-0ddb-4fd2-b48a-15a1b7511e52', // Overlapping empty circles
'3c892452-3806-4ebf-821b-a76f4562dd0c', // points and lines
'21cc8261-e626-4778-a78b-76fe8b808214', // markers tilesets
'4e8f215f-97b4-4f4e-8b53-465c3908c317' // markers points
'4e8f215f-97b4-4f4e-8b53-465c3908c317', // markers points
'27de26b4-b94f-4e94-b291-41d1a21d3d02' // HexColumn color
];
const params = new URLSearchParams(location.search.slice(1));
const id = params.has('id') ? params.get('id') : examples[0];
Expand Down

0 comments on commit 157b988

Please sign in to comment.