Use discrete colors for distances, with greens only above 1.5m
This commit is contained in:
parent
6893d7b56f
commit
1c52ce7de9
|
@ -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 (
|
||||
<div className={styles.colorMapLegend}>
|
||||
<svg width="100%" height="20" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||
<defs>
|
||||
<linearGradient id={gradientId} x1="0" x2="1" y1="0" y2="0">
|
||||
{parts.map(([[left, right], color]) => (
|
||||
<React.Fragment key={left}>
|
||||
<stop offset={normalizeValue(left) * 100 + '%'} stopColor={color} />
|
||||
<stop offset={normalizeValue(right) * 100 + '%'} stopColor={color} />
|
||||
</React.Fragment>
|
||||
|
||||
))}
|
||||
</linearGradient>
|
||||
</defs>
|
||||
|
||||
<rect id="rect1" x="0" y="0" width="100%" height="100%" fill={gradientUrl} />
|
||||
</svg>
|
||||
|
||||
{stops.map((value) => (
|
||||
<span className={styles.tick} key={value} style={{left: normalizeValue(value) * 100 + '%'}}>
|
||||
{value.toFixed(2)}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default function ColorMapLegend({map, twoTicks = false}: {map: ColorMap, twoTicks?: boolean}) {
|
||||
const min = map[0][0]
|
||||
const max = map[map.length - 1][0]
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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({
|
|||
) :
|
||||
(
|
||||
<List.Item>
|
||||
<ColorMapLegend map={_.chunk(colorByDistance('distance_overtaker')[3].slice(3), 2)} />
|
||||
<DiscreteColorMapLegend map={colorByDistance('distance_overtaker')[3].slice(2)} />
|
||||
</List.Item>
|
||||
)}
|
||||
</>
|
||||
|
@ -120,7 +120,7 @@ function LayerSidebar({
|
|||
{showEvents && (
|
||||
<>
|
||||
<List.Item>
|
||||
<ColorMapLegend map={_.chunk(colorByDistance('distance_overtaker')[3].slice(3), 2)} />
|
||||
<DiscreteColorMapLegend map={colorByDistance('distance_overtaker')[3].slice(2)} />
|
||||
</List.Item>
|
||||
</>
|
||||
)}
|
||||
|
|
Loading…
Reference in a new issue