sloy-map
v0.1.3
Published
Set up a beautiful geoportal using config. No code.
Downloads
4
Readme
Set up a beautiful geoportal using config. No code.
Features
- All features from mapbox \ maplibre \ deck.gl
- JSON configuration (can be stored on the backend)
- Custom geojson & vector tiles filters
- Custom geojson & vector tiles visualisation
- License, copyright and metadata management
- Low level api via redux actions
- Custom files loader
- Custom projections
- Built-in responsive version
- Pmtiles support
- Basemap setup
- Themes
- Localisation
- Terrain
- Countours
- Typescript-safe
Tldr;
Main details:
- Library is a maplibre map wrapper.
- You can use any features from mapbox \ maplibre \ deck.gl
- Library has 5 main entities: sources, layers, visualization, filter, card
- Source: data source (geojson, json, vector tile), technically is a wrapper for mabplibre Source with extra params
- Visualization: wrapper for the mabplibre Layer with extra params.
- Filter: configuration for custom ui that helps to filter source data
- Layer: group of visualizations and filters
- Card: popup for selected data
Installation
npm i sloy-map
npm i react-redux @reduxjs/toolkit
import { Provider } from "react-redux";
import { configureStore } from "@reduxjs/toolkit";
import { SloyMap, sloyReducer } from "sloy-map";
import 'sloy-map/style.css';
const store = configureStore({
reducer: {
sloy: sloyReducer,
},
});
export function App() {
return (
<Provider store={store}>
<SloyMap
mapState={{
initialViewState: {
zoom: 14.5,
longitude: 44.51,
latitude: 40.18,
},
mapStyle: "https://sloy.io/armenia/style.json",
}}
sources={[
{
id: "sourceId",
path: "/file.geojson",
type: "geojson",
// also you can use { type: "json" }
// with latProperty, lngProperty, coordsProperty, isCoordsReverse for custom lat\lng keys
// you can use custom projection here
// supports proj4 format
projection: "EPSG:28408",
properties: [
{
id: "VALUE",
title: "kcal/cm²",
// you can describe data colors here, this colors can be used in the visualisations and filters
values: {
40: { color: "#fddede" },
45: { color: "#feb7b9" },
50: { color: "#fd9793" },
},
},
{
id: "UNIT",
title: "Units",
},
],
// you can describe popup content using the keys from the data
card: {
title: "name",
blocks: [{ type: "value", id: "VALUE" }],
},
copyright: [],
mapSourceProps: {
/* any mapbox\maplibre source props */
},
},
]}
layers={[
{
id: "layerId",
title: "Geojson example",
description: "Description",
filters: [],
visualizations: [
{
id: "visualizationId",
source: "sourceId",
openable: true,
property: "VALUE",
type: "map",
// any mapbox\maplibre props:
mapLayerProps: {
type: "fill",
paint: {
"fill-opacity": 0.6,
},
},
},
],
},
]}
mapProps={
{
/* you can use mapbox\maplibre map props here
for example mapboxAccessToken: xxxx */
}
}
/>
</Provider>
);
}
You can find more examples in the src/examples/ folder
API
Map props
export interface SloyMapProps extends MapContextProps {
mapState: IMapState;
mapProps?: IMapProps;
sources: InputSloySource[];
layers: InputSloyLayer[];
theme?: typeof styled-components ThemeProvider;
copyrights?: ICopyright[];
children?: ReactNode;
locale?: string;
translations?: Record<string, Record<string, string>>;
overrideCard?: OverrideCardFn;
overrideLayers?: OverrideLayersFn;
terrainSource?: string;
layout?: {
hasBaseMap?: boolean;
hasPmtiles?: boolean;
buildingLayerName?: string;
loaderImageSrc?: string;
canSelectMultipleLayers?: boolean;
};
}
Source
interface ISource {
id: string;
mapSourceProps?: typeof maplibre.Source;
// path to file
path?: string;
type: "vector-tiles" | "geojson" | "json";
properties?: Record<string, SourceProperty>;
card?: ICard["id"];
isCoordsReverse?: boolean;
coordsProperty?: string;
latProperty?: string;
lngProperty?: string;
projection?: string;
dataByIdPath?: string;
copyright: Copyright["id"][];
}
Layer
interface ILayer {
id: string;
title: string;
description?: string;
updatedAt?: string;
link?: {
label?: string;
href?: string;
};
license?: string;
filters: IFilter["id"][];
visualizations: IVisualization["id"][];
initialViewState?: {
center?: number[];
};
}
Visualization
interface IVisualization {
id: string;
type: "map" | "building-ids" | "marker-image" | "building-range" | "native";
source: ISource["id"];
property?: string;
previewPath?: string;
rootSrc?: string;
ids?: string[];
openable?: boolean;
mapLayerProps?: typeof maplibre.Layer;
}
Filter
interface IFilter {
id: string;
source: ISource["id"];
type: "boolean" | "range" | "string" | "string[]";
filterVisualizations: IVisualization["id"][];
sortType?: "config" | "count" | "alphabetical";
totalHeader?: "count";
title?: string;
description?: string;
property?: string;
color?: string;
subTitle?: string;
totalType?: "percent";
postfix?: string;
}
Card
interface ICard {
id: string;
cover?: string;
title?: string | string[];
description?: string | string[];
additionalInfo?: string[];
blocks: ICardBlock[];
rootSrc?: string;
}
interface ICardBlock {
type: string;
id?: string;
deps?: string;
content?: string;
dateTimeFormat?: Intl.DateTimeFormatOptions;
title?: string | null;
value?: ReactNode;
}
Copyright
interface ICopyright {
id: string;
shortName: string;
fullName?: string;
url: string;
requiredAttribution?: boolean;
}
Contribution
pnpm i
pnpm start