Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Discrete color scales with < 3 values + display lakes and rivers #309

Merged
merged 10 commits into from
Feb 8, 2022
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

### Features

- Page have improved titles now, depending on where you are on the application. Helpful when you have
multiple tabs with visualize.admin or when you bookmark things. [#331](https://github.com/visualize-admin/visualization-tool/pull/331)
- Theme and organization navigation counts take into account the search field now. [#329](https://github.com/visualize-admin/visualization-tool/pull/329)
- Added rivers and lakes through vector layer [#309](https://github.com/visualize-admin/visualization-tool/pull/309)

### Bugs

- Fix selection of optional date filter [#332](https://github.com/visualize-admin/visualization-tool/pull/332)
- Fix discrete color scales with less than 3 observations [#309](https://github.com/visualize-admin/visualization-tool/pull/309)]

## [3.3.0] - 2022-02-07

Expand Down
2 changes: 1 addition & 1 deletion app/charts/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ export const getInitialConfig = ({
},
baseLayer: {
showRelief: true,
showLakes: true,
showWater: true,
},
};

Expand Down
35 changes: 5 additions & 30 deletions app/charts/map/chart-map.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { geoCentroid } from "d3";
import React, { memo, useEffect, useMemo, useState } from "react";
import React, { memo, useMemo } from "react";
import { Box } from "theme-ui";
import {
feature as topojsonFeature,
Expand Down Expand Up @@ -32,11 +32,6 @@ import { MapLegend } from "./map-legend";
import { MapChart } from "./map-state";
import { MapTooltip } from "./map-tooltip";

type GeoDataState =
| { state: "fetching" }
| { state: "error" }
| (GeoData & { state: "loaded" });

export const ChartMapVisualization = ({
dataSetIri,
chartConfig,
Expand All @@ -46,7 +41,6 @@ export const ChartMapVisualization = ({
chartConfig: MapConfig;
queryFilters: QueryFilters;
}) => {
const [geoData, setGeoData] = useState<GeoDataState>({ state: "fetching" });
const locale = useLocale();

const areaDimensionIri = chartConfig.fields.areaLayer.componentIri;
Expand Down Expand Up @@ -161,40 +155,21 @@ export const ChartMapVisualization = ({
}
}, [areaLayer, dimensions, observations, symbolDimensionIri, geoCoordinates]);

useEffect(() => {
const loadLakes = async () => {
try {
const res = await fetch(`/topojson/ch-2020.json`);
const topo = await res.json();
const lakes = topojsonFeature(
topo,
topo.objects.lakes
) as any as GeoJSON.FeatureCollection;

setGeoData({ state: "loaded", lakes });
} catch (e) {
setGeoData({ state: "error" });
}
};

loadLakes();
}, []);

if (measures && dimensions && observations && geoData.state === "loaded") {
if (measures && dimensions && observations) {
return (
<ChartMapPrototype
observations={observations}
features={{ ...geoData, areaLayer, symbolLayer }}
features={{ areaLayer, symbolLayer }}
fields={chartConfig.fields}
measures={measures}
dimensions={dimensions}
baseLayer={chartConfig.baseLayer}
geoShapes={geoShapes}
/>
);
} else if (geoData.state === "fetching" || fetching) {
} else if (fetching) {
return <Loading />;
} else if (geoData.state === "error" || error) {
} else if (error) {
return <LoadingDataError />;
} else {
return <NoDataHint />;
Expand Down
7 changes: 6 additions & 1 deletion app/charts/map/map-legend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,15 @@ const makeAxis = (

export const MapLegend = () => {
const { areaLayer, symbolLayer } = useChartState() as MapState;
const showAreaLegend =
areaLayer.show &&
areaLayer.data.length >= 3 &&
(areaLayer.colorScaleInterpolationType === "linear" ||
areaLayer.colorScale.range().length >= 3);

return (
<Flex sx={{ minHeight: 100, flexWrap: "wrap" }}>
{areaLayer.show && (
{showAreaLegend && (
<Box sx={{ p: 4 }}>
{areaLayer.measureLabel && (
<Text
Expand Down
6 changes: 3 additions & 3 deletions app/charts/map/map-state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export interface MapState {
bounds: Bounds;
features: GeoData;
showRelief: boolean;
showLakes: boolean;
showWater: boolean;
identicalLayerComponentIris: boolean;
areaLayer: {
data: Observation[];
Expand Down Expand Up @@ -118,7 +118,7 @@ const getColorScale = ({
case "jenks":
const ckMeansThresholds = ckmeans(
data.map((d) => getValue(d) ?? NaN),
nbClass
Math.min(nbClass, data.length)
).map((v) => v.pop() || 0);

return scaleThreshold<number, string>()
Expand Down Expand Up @@ -278,7 +278,7 @@ const useMapState = ({
features,
bounds,
showRelief: baseLayer.showRelief,
showLakes: baseLayer.showLakes,
showWater: baseLayer.showWater,
identicalLayerComponentIris,
areaLayer: {
data: areaData,
Expand Down
61 changes: 35 additions & 26 deletions app/charts/map/map.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { MapController, WebMercatorViewport } from "@deck.gl/core";
import { TileLayer } from "@deck.gl/geo-layers";
import { MVTLayer, TileLayer } from "@deck.gl/geo-layers";
import { BitmapLayer, GeoJsonLayer, ScatterplotLayer } from "@deck.gl/layers";
import DeckGL from "@deck.gl/react";
import React, { useCallback, useMemo, useState } from "react";
Expand All @@ -21,12 +21,15 @@ type TileData = {
signal: { aborted: boolean };
};

const MIN_ZOOM = 3;
const MAX_ZOOM = 13;

const INITIAL_VIEW_STATE = {
latitude: 46.8182,
longitude: 8.2275,
zoom: 5,
maxZoom: 16,
minZoom: 2,
minZoom: MIN_ZOOM,
maxZoom: MAX_ZOOM,
pitch: 0,
bearing: 0,
};
Expand Down Expand Up @@ -94,7 +97,7 @@ const constrainZoom = (
export const MapComponent = () => {
const {
showRelief,
showLakes,
showWater,
features,
identicalLayerComponentIris,
areaLayer,
Expand Down Expand Up @@ -172,6 +175,7 @@ export const MapComponent = () => {
<ZoomButton iconName="minus" handleClick={zoomOut} />
</Box>
<DeckGL
mapStyle="https://basemaps.cartocdn.com/gl/dark-matter-gl-style/style.json"
viewState={viewState}
onViewStateChange={onViewStateChange}
onResize={onResize}
Expand All @@ -180,17 +184,17 @@ export const MapComponent = () => {
>
{showRelief && (
<TileLayer
getTileData={({ z, x, y }: TileData) =>
`https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.leichte-basiskarte_reliefschattierung/default/current/3857/${z}/${x}/${y}.png`
}
id="relief"
data="https://wmts.geo.admin.ch/1.0.0/ch.swisstopo.leichte-basiskarte_reliefschattierung/default/current/3857/{z}/{x}/{y}.png"
tileSize={256}
pickable={false}
minZoom={2}
maxZoom={16}
maxCacheSize={512}
minZoom={MIN_ZOOM}
maxZoom={MAX_ZOOM}
renderSubLayers={(props: { tile: TileData; data: $FixMe }) => {
const {
bbox: { west, south, east, north },
} = props.tile;

return [
new BitmapLayer(props, {
data: null,
Expand Down Expand Up @@ -248,7 +252,7 @@ export const MapComponent = () => {
if (observation) {
const value = areaLayer.getValue(observation);

if (value) {
if (value !== null) {
return areaLayer.getColor(value);
}
}
Expand All @@ -272,21 +276,26 @@ export const MapComponent = () => {
</>
)}

{showLakes && (
<GeoJsonLayer
id="lakes"
data={features.lakes}
pickable={false}
stroked={true}
filled={true}
extruded={false}
lineWidthMinPixels={0.5}
lineWidthMaxPixels={1}
getLineWidth={100}
getFillColor={[102, 175, 233]}
getLineColor={[255, 255, 255]}
/>
)}
<MVTLayer
id="water"
data={[
"https://vectortiles0.geo.admin.ch/tiles/ch.swisstopo.leichte-basiskarte.vt/v1.0.0/{z}/{x}/{y}.pbf",
"https://vectortiles1.geo.admin.ch/tiles/ch.swisstopo.leichte-basiskarte.vt/v1.0.0/{z}/{x}/{y}.pbf",
"https://vectortiles2.geo.admin.ch/tiles/ch.swisstopo.leichte-basiskarte.vt/v1.0.0/{z}/{x}/{y}.pbf",
"https://vectortiles3.geo.admin.ch/tiles/ch.swisstopo.leichte-basiskarte.vt/v1.0.0/{z}/{x}/{y}.pbf",
"https://vectortiles4.geo.admin.ch/tiles/ch.swisstopo.leichte-basiskarte.vt/v1.0.0/{z}/{x}/{y}.pbf",
]}
tileSize={256}
getLineColor={[255, 255, 255, 0]}
getFillColor={(d: any) => {
return showWater && d.properties.layerName === "water"
? [148, 198, 240]
: [148, 198, 240, 0];
}}
updateTriggers={{
getFillColor: [showWater],
}}
/>

{symbolLayer.show && (
<ScatterplotLayer
Expand Down
4 changes: 2 additions & 2 deletions app/configurator/components/chart-configurator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,8 @@ const ChartFields = ({
icon="baseLayer"
label={<Trans id="chart.map.layers.base">Base Layer</Trans>}
active={
chartConfig.baseLayer.showLakes ||
chartConfig.baseLayer.showRelief
chartConfig.baseLayer.showRelief ||
chartConfig.baseLayer.showWater
}
/>
) : (
Expand Down
2 changes: 1 addition & 1 deletion app/configurator/config-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ export type MapSymbolLayer = t.TypeOf<typeof MapSymbolLayer>;

const BaseLayer = t.type({
showRelief: t.boolean,
showLakes: t.boolean,
showWater: t.boolean,
});
export type BaseLayer = t.TypeOf<typeof BaseLayer>;
const MapFields = t.type({
Expand Down
6 changes: 3 additions & 3 deletions app/configurator/map/map-chart-options.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ export const BaseLayersSettings = memo(() => {
/>
<ChartOptionCheckboxField
label={t({
id: "chart.map.layers.base.show.lakes",
message: "Show lakes",
id: "chart.map.layers.base.show.water",
message: "Show lakes and rivers",
})}
field={null}
path="baseLayer.showLakes"
path="baseLayer.showWater"
/>
</ControlSectionContent>
</ControlSection>
Expand Down
1 change: 0 additions & 1 deletion app/domain/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ export type SymbolLayer = {
};

export type GeoData = {
lakes: GeoJSON.FeatureCollection;
areaLayer?: AreaLayer;
symbolLayer?: SymbolLayer;
};
Expand Down
Loading