diff --git a/frontend/src/components/ColorMapLegend.tsx b/frontend/src/components/ColorMapLegend.tsx index 8430be8..f0c4d48 100644 --- a/frontend/src/components/ColorMapLegend.tsx +++ b/frontend/src/components/ColorMapLegend.tsx @@ -1,9 +1,64 @@ -import {useMemo} from "react"; +import React, {useMemo} from "react"; type ColorMap = [number, string][] import styles from './ColorMapLegend.module.less' +function* pairs(arr) { + for (let i = 1; i < arr.length; i++) { + yield [arr[i - 1], arr[i]]; + } +} +function* zip(...arrs) { + const l = Math.min(...arrs.map(a => a.length)); + for (let i = 0; i < l; i++) { + yield arrs.map(a => a[i]); + } +} + +export function DiscreteColorMapLegend({map}: {map: ColorMap}) { + const colors: string[] = map.filter((x, i) => i % 2 == 0) as any + const stops: number[] = map.filter((x, i) => i % 2 == 1) as any + let min = stops[0] + let max = stops[stops.length - 1] + const buffer = (max - min) / (stops.length - 1) / 2 + min -= buffer + max += buffer + const normalizeValue = (v) => (v - min) / (max - min) + const stopPairs = Array.from(pairs([min, ...stops, max])); + + const gradientId = useMemo(() => `gradient${Math.floor(Math.random() * 1000000)}`, []); + const gradientUrl = `url(#${gradientId})`; + + const parts = Array.from(zip(stopPairs, colors)) + + return ( +
+ + + + {parts.map(([[left, right], color]) => ( + + + + + + ))} + + + + + + + {stops.map((value) => ( + + {value.toFixed(2)} + + ))} +
+ ) +} + export default function ColorMapLegend({map, twoTicks = false}: {map: ColorMap, twoTicks?: boolean}) { const min = map[0][0] const max = map[map.length - 1][0] diff --git a/frontend/src/components/index.js b/frontend/src/components/index.js index ae1cc8a..a7ed811 100644 --- a/frontend/src/components/index.js +++ b/frontend/src/components/index.js @@ -1,5 +1,5 @@ export {default as Avatar} from './Avatar' -export {default as ColorMapLegend} from './ColorMapLegend' +export {default as ColorMapLegend, DiscreteColorMapLegend} from './ColorMapLegend' export {default as FileDrop} from './FileDrop' export {default as FileUploadField} from './FileUploadField' export {default as FormattedDate} from './FormattedDate' diff --git a/frontend/src/mapstyles/index.js b/frontend/src/mapstyles/index.js index e16c1ca..56a8449 100644 --- a/frontend/src/mapstyles/index.js +++ b/frontend/src/mapstyles/index.js @@ -53,13 +53,13 @@ export function colorByDistance(attribute = 'distance_overtaker_mean', fallback ['!', ['to-boolean', ['get', attribute]]], fallback, [ - 'interpolate-hcl', - ['linear'], + 'step', ['get', attribute], - 1, + 'rgba(150, 0, 0, 1)', + 1.1, 'rgba(255, 0, 0, 1)', 1.3, - 'rgba(255, 200, 0, 1)', + 'rgba(255, 220, 0, 1)', 1.5, 'rgba(67, 200, 0, 1)', 1.7, diff --git a/frontend/src/pages/MapPage/LayerSidebar.tsx b/frontend/src/pages/MapPage/LayerSidebar.tsx index cc0b781..9e38026 100644 --- a/frontend/src/pages/MapPage/LayerSidebar.tsx +++ b/frontend/src/pages/MapPage/LayerSidebar.tsx @@ -9,7 +9,7 @@ import { initialState as defaultMapConfig, } from 'reducers/mapConfig' import {colorByDistance, colorByCount, viridisSimpleHtml} from 'mapstyles' -import {ColorMapLegend} from 'components' +import {ColorMapLegend, DiscreteColorMapLegend} from 'components' const BASEMAP_STYLE_OPTIONS = [ {value: 'positron', key: 'positron', text: 'Positron'}, @@ -98,7 +98,7 @@ function LayerSidebar({ ) : ( - + )} @@ -120,7 +120,7 @@ function LayerSidebar({ {showEvents && ( <> - + )}