Style adjustments
Apply adjustments to a map's vector style — roads in white, labels off, darker water — as declarative rules. The same rules work unchanged on Android and iOS.
01 · Overview
A rule pairs a selector (which layers) with a patch (what to change). Selectors can name a role — roads, water, labels — rather than layer ids. The OpenMapTiles, Shortbread and Mapbox Streets schemas are recognised automatically, so you do not have to look up each style's layer ids.
Pass what createVectorStyle() returns to any *MapView as mapStyle. In React style is the element's own CSS, hence the name (on Android and iOS it is style).
VectorTileRasteriser as the rasteriserHand it to a map that cannot read vector styles without a rasteriser and the diagnostics say the style is unsupported, rather than the map quietly drawing nothing.
02 · Install
npm install @mapconductor/js-sdk-core @mapconductor/js-vectorstyle
To use it on maps without a vector renderer, add react-vectortile for the rasteriser too (and set up the Service Worker described in vector tile layer).
npm install @mapconductor/react-vectortile
ESM only. The rules compiler is wasm (about 190 KB), loaded relative to import.meta.url; Vite handles that as is. Serve it from elsewhere with wasmUrl.
03 · Basic usage
Leave out document and the style the map is already drawing ('currentDesign') is adjusted. The example turns MapLibre's default design into a black-and-white map of roads.
import { useMemo } from 'react';
import { buildStyleRules, createVectorStyle, LayerRole } from '@mapconductor/js-vectorstyle';
import { MapLibreMapView2D, useMapLibreViewState } from '@mapconductor/react-for-maplibre';
export function RoadsOnlyMap() {
const state = useMapLibreViewState();
const mapStyle = useMemo(
() => createVectorStyle({
rules: buildStyleRules((r) => {
r.all({ color: '#000000' });
r.role(LayerRole.label, { visible: false });
r.role(LayerRole.roadCasing, { color: '#303030' });
r.role(LayerRole.road, { color: '#ffffff', widthScale: 1.4 });
}),
}),
[],
);
return (
<MapLibreMapView2D
state={state}
mapStyle={mapStyle}
onStyleDiagnostics={(messages) => console.warn(messages)}
/>
);
}For a style of your own, pass { url } or { text } as document.
04 · Writing rules
Rules apply in order and, as in CSS, a later rule wins property by property. Set the whole map with all, then override by role.
buildStyleRules((r) => {
r.all({ colorFilter: { darken: 0.55 } });
r.role(LayerRole.water, { color: 'rgb(10,28,43)' });
r.role(LayerRole.road, { color: '#d0d0d0' });
r.layerId('poi-*', { visible: false });
r.kind('symbol', { opacity: 0.8 });
});* and ? wildcards.Rules as JSON
Rules are also a JSON document. To serve them from a server or keep them across app versions, store them in this form and read them with parseStyleRules(). Android and iOS read the same document.
{
"schemaVersion": 1,
"rules": [
{ "selector": "all", "patch": { "colorFilter": { "darken": 0.55 } } },
{ "selector": { "role": "water" }, "patch": { "color": "rgb(10,28,43)" } }
]
}import { createVectorStyle, parseStyleRules } from '@mapconductor/js-vectorstyle';
const rules = parseStyleRules(await (await fetch('/night.rules.json')).text());
const mapStyle = createVectorStyle({ rules });05 · On maps without a vector renderer
Pass a VectorTileRasteriser as rasteriser and the style is drawn into raster tiles and layered on. Blank the provider's own basemap with its None design.
import { useMemo } from 'react';
import { createVectorStyle } from '@mapconductor/js-vectorstyle';
import { VectorTileRasteriser } from '@mapconductor/react-vectortile';
import { GoogleMapDesign, GoogleMapView2D, useGoogleMapViewState } from '@mapconductor/react-for-googlemaps';
const state = useGoogleMapViewState({
apiKey: import.meta.env.VITE_GOOGLE_MAPS_API_KEY,
mapDesignType: GoogleMapDesign.None,
});
const rasteriser = useMemo(() => new VectorTileRasteriser(), []);
const mapStyle = useMemo(
() => createVectorStyle({
document: { url: 'https://tiles.versatiles.org/assets/styles/colorful/style.json' },
rules,
rasteriser,
}),
[rules, rasteriser],
);
<GoogleMapView2D state={state} mapStyle={mapStyle} style={{ height: 480 }} />useMemo or similar.06 · Options
{ url, headers? }, { text } or 'currentDesign'.NO_STYLE_RULES keeps the style as authored.'reload' hands it the whole adjusted document — correct, but expensive.Diagnostics also arrive through the *MapView's onStyleDiagnostics; without it they go to the console. A rule that matched nothing only looks like "it nearly worked", so keep them visible while you build.