Skip to main content
Forecasts
Mathematical models data could be provided as a tile layer on demand. You can see how to integrate tiles into your map in the examples below
Parameters
Domain:domain identifier
Height:integer, height layer number. Starts from 0 (surface layer)
Substance:string identifier, for example PM25
Date:format: YYYYMMDD_HH0000, example: 20230915_080000
Only last 6 months available, forecast step is 1 hour
Vector tiles usage example
Forecast path template:
https://tiles.cityair.io/v1/public/forecast/DOMAIN/raster/custom/HEIGHT/SUBSTANCE/DATE.json
Mapbox example:
Javascript source code:
/components/Map.js

const COLORS = [
'1', '#B8BFCC',
'2', '#8CB917',
'3', '#A2C617',
'4', '#BEC617',
'5', '#FFCC33',
'6', '#FFA33B',
'7', '#FF7344',
'8', '#FF494B',
'9', '#D63B50',
'10', '#AD2D55',
];

function Vector() {
const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(37.345);
const [lat, setLat] = useState(55.872);
const [zoom, setZoom] = useState(5.5);


useEffect(() => {
if (map.current) return; // initialize map only once
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/streets-v11',
center: [lng, lat],
zoom: zoom
});
});

useEffect(() => {
if (!map.current) return; // wait for map to initialize
map.current.on('move', () => {
setLng(map.current.getCenter().lng.toFixed(4));
setLat(map.current.getCenter().lat.toFixed(4));
setZoom(map.current.getZoom().toFixed(2));
});
map.current.on('load', () => {
map.current.addSource(
'vect', {
'type': 'geojson',
'data': ' https://tiles.cityair.io/v1/public/forecast/ru_moscow_5.0km/vector/custom/0/PM25/20230915_080000.json '
});

map.current.addLayer({
'id': 'vect',
'type': 'fill',
'source': 'vect',
'layout': {},
'paint': {
'fill-color': ['match', ['get', 'lvl'], ...COLORS, COLORS[1]],
'fill-opacity': 0.5
}
});
});
});

return (
<div>
<div ref={mapContainer} className="map-container" />
</div>
);
}

Raster tiles usage example
Forecast path template:
https://tiles.cityair.io/v1/public/forecast/DOMAIN/vector/custom/HEIGHT/SUBSTANCE/DATE.png
Mapbox example:
Javascript source code:
/components/Map.js

function Raster() {
const mapContainer = useRef(null);
const map = useRef(null);
const [lng, setLng] = useState(37.345);
const [lat, setLat] = useState(55.872);
const [zoom, setZoom] = useState(5.5);


useEffect(() => {
if (map.current) return; // initialize map only once
map.current = new mapboxgl.Map({
container: mapContainer.current,
style: 'mapbox://styles/mapbox/streets-v11',
center: [lng, lat],
zoom: zoom
});
});

useEffect(() => {
if (!map.current) return; // wait for map to initialize
map.current.on('move', () => {
setLng(map.current.getCenter().lng.toFixed(4));
setLat(map.current.getCenter().lat.toFixed(4));
setZoom(map.current.getZoom().toFixed(2));
});
map.current.on('load', () => {
map.current.addSource('radar', {
'type': 'image',
'url': 'https://tiles.cityair.io/v1/public/forecast/ru_moscow_5.0km/raster/custom/0/PM25/20230915_080000.png',
'coordinates': [
[35.482452392578125, 56.42679977416992],
[39.207977294921875, 56.42679977416992],
[39.207977294921875, 54.11769485473633],
[35.482452392578125, 54.11769485473633]
],
});
map.current.addLayer({
id: 'radar-layer',
'type': 'raster',
'source': 'radar',
'paint': {
'raster-fade-duration': 0,
'raster-opacity': 0.5
}
});
});
});

return (
<div>
<div ref={mapContainer} className="map-container" />
</div>
);
}