In this page
<gui-map />
Maplibregl
This component relies on maplibre-gl
in order to work. This library is not vendored with @greycat/web
, it is your responsibility to define maplibregl
globally prior to initializing the SDK:
import '@greycat/web';
import maplibregl from 'maplibre-gl';
await gc.sdk.init({ maplibregl }); // this tells GreyCat to also load the components that rely on `maplibregl`
Markers example
Display markers on a map from a sampled nodeGeo
that uses cities.csv
const el = document.createElement('div');
el.style.height = '600px';
const markers = document.createElement('gui-map-markers');
const map = document.createElement('gui-map');
map.options = {
style: 'style.json',
center: gc.core.geo.fromLatLng(49.6181, 6.162),
zoom: 3,
};
el.appendChild(map);
map.appendChild(markers);
const root = await gc.$.default.root();
const nCities = root['project::cities'];
map.ready.then((m) => {
m.on('zoomend', updateCities);
m.on('dragend', updateCities);
async function updateCities() {
const bounds = m.getBounds();
const tCities = await gc.core.nodeGeo.sample(
[nCities],
gc.core.geo.fromLatLng(bounds.getSouthWest()),
gc.core.geo.fromLatLng(bounds.getNorthEast()),
1000,
gc.core.SamplingMode.dense,
);
const cities = [];
for (const row of tCities) {
cities.push({ geo: row[0], data: row[1] });
}
markers.value = cities;
}
updateCities();
});
var cities: nodeGeo<City>;
type City {
country: String;
name: String;
location: geo;
population: int;
type: CapitalType;
}
enum CapitalType {
Others,
"Administrative Capital",
"Seat of Government",
Capital,
"Legislative Capital",
"Economic Capital",
}
fn import() {
if (cities.size() != 0) {
return;
}
var reader = CsvReader<City> {
path: "csv/cities.csv",
format: CsvFormat {
header_lines: 1,
},
};
while (reader.can_read()) {
var record = reader.read();
cities.set(record.location, record);
}
}
Heatmap example
Displays earthquakes as a heatmap based on there magnitude. The data is available at earthquakes_4.5_month.csv
.
const el = document.createElement('div');
el.style.position = 'relative';
el.style.height = '600px';
// Fetch data from GreyCat
const earthquakes = await gc.project.earthquakes();
// Convert the array to a GeoJSON.FeatureCollection
const geojson = earthquakes.toFeatureCollection((e) => ({
type: 'Point',
coordinates: [e.location.lat, e.location.lng],
}));
const drawer = document.createElement('sl-drawer');
drawer.label = 'Earthquake';
drawer.contained = true;
drawer.placement = 'start';
drawer.style.position = 'absolute';
drawer.style.setProperty('--width', '400px');
const hoveredDisplay = document.createElement('gui-object');
let hoveredId;
const footer = document.createElement('sl-button');
footer.slot = 'footer';
footer.variant = 'primary';
footer.onclick = () => drawer.hide();
footer.textContent = 'Close';
drawer.append(hoveredDisplay, footer);
const map = document.createElement('gui-map');
map.options = {
style: 'style.json',
center: gc.core.geo.fromLatLng(49.6181, 6.162),
zoom: 3,
};
map.ready.then((m) => {
m.addSource('earthquakes', { type: 'geojson', data: geojson });
m.addLayer({
'id': 'earthquakes-heat',
'type': 'heatmap',
'source': 'earthquakes',
'maxzoom': 9,
'paint': {
// Increase the heatmap weight based on frequency and property magnitude
'heatmap-weight': ['interpolate', ['linear'], ['get', 'mag'], 0, 0, 6, 1],
// Increase the heatmap color weight weight by zoom level
// heatmap-intensity is a multiplier on top of heatmap-weight
'heatmap-intensity': ['interpolate', ['linear'], ['zoom'], 0, 1, 9, 3],
// Color ramp for heatmap. Domain is 0 (low) to 1 (high).
// Begin color ramp at 0-stop with a 0-transparency color
// to create a blur-like effect.
'heatmap-color': [
'interpolate',
['linear'],
['heatmap-density'],
0, 'rgba(33,102,172,0)',
0.2, 'rgb(103,169,207)',
0.4, 'rgb(209,229,240)',
0.6, 'rgb(253,219,199)',
0.8, 'rgb(239,138,98)',
1, 'rgb(178,24,43)'
],
// Adjust the heatmap radius by zoom level
'heatmap-radius': ['interpolate', ['linear'], ['zoom'], 0, 2, 9, 20],
// Transition from heatmap to circle layer by zoom level
'heatmap-opacity': ['interpolate', ['linear'], ['zoom'], 7, 1, 9, 0]
}
});
m.addLayer({
'id': 'earthquakes-point',
'type': 'circle',
'source': 'earthquakes',
'minzoom': 7,
'paint': {
// Size circle radius by earthquake magnitude and zoom level
'circle-radius': [
'interpolate',
['linear'],
['zoom'],
7,
['interpolate', ['linear'], ['get', 'mag'], 1, 1, 6, 4],
16,
['interpolate', ['linear'], ['get', 'mag'], 1, 5, 6, 50]
],
// Color circle by earthquake magnitude
'circle-color': [
'interpolate',
['linear'],
['get', 'mag'],
1, 'rgba(33,102,172,0)',
2, 'rgb(103,169,207)',
3, 'rgb(209,229,240)',
4, 'rgb(253,219,199)',
5, 'rgb(239,138,98)',
6, 'rgb(178,24,43)'
],
// Update the circle stroke color based on the hovered state
'circle-stroke-color': ['case', ['boolean', ['feature-state', 'hover'], false], 'rgb(192,248,95)', 'white'],
'circle-stroke-width': ['case', ['boolean', ['feature-state', 'hover'], false], 3, 1],
// Transition from heatmap to circle layer by zoom level
'circle-opacity': ['interpolate', ['linear'], ['zoom'], 7, 0, 8, 1]
}
});
m.on('mousemove', 'earthquakes-point', (e) => {
if (!e.features || e.features.length === 0 || hoveredId === e.features[0].id) {
return;
}
if (hoveredId) {
m.setFeatureState({ source: 'earthquakes', id: hoveredId }, { hover: false });
}
hoveredId = e.features[0].id;
m.setFeatureState({ source: 'earthquakes', id: hoveredId }, { hover: true });
hoveredDisplay.value = earthquakes[hoveredId];
drawer.show();
});
});
el.append(map, drawer);
var earthquakes_by_geo: nodeGeo<Earthquake>;
var earthquakes_by_time: nodeTime<Earthquake>;
type Earthquake {
time: time;
location: geo;
depth: float;
mag: float;
magType: MagType;
nst: int?;
gap: int?;
dmin: float?;
rms: float;
net: Net;
id: String;
updated: time;
place: String;
horizontalError: float?;
depthError: float;
magError: float?;
magNst: int?;
magSource: MagSource;
}
@volatile
private type Record {
/// column=0
@format("%Y-%m-%dT%H:%M:%S%z")
time: time;
/// column=1, min=-61.8842, max=83.8394, avg=22.4896408333
latitude: float;
/// column=2, min=-179.369, max=179.8605, avg=83.5534406667
longitude: float;
/// column=3, min=7.466, max=639.511, avg=55.0781866667
depth: float;
/// column=4, min=4.5, max=7.8, avg=4.8468333333
mag: float;
/// column=5
magType: MagType;
/// column=6, min=9, max=287, avg=63.9296482412
nst: int?;
/// column=7, min=20, max=263, avg=108.076599665
gap: int?;
/// column=8, min=0.1, max=31.484, avg=2.6537839196
dmin: float?;
/// column=9, min=0.32, max=1.55, avg=0.8291103333
rms: float;
/// column=10
net: Net;
/// column=11
id: String;
/// column=12
@format("%Y-%m-%dT%H:%M:%S%z")
updated: time;
/// column=13
place: String;
/// column=14
type: Type;
/// column=15, min=2.88, max=17.47, avg=8.7943456376
horizontalError: float?;
/// column=16, min=0.972, max=22.5, avg=4.4283683333
depthError: float;
/// column=17, min=0.02, max=0.205, avg=0.0727785235
magError: float?;
/// column=18, min=7, max=818, avg=101.1375838926
magNst: int?;
/// column=19
status: Status;
/// column=20
locationSource: LocationSource;
/// column=21
magSource: MagSource;
}
enum MagType {
mww,
ml,
mw,
mwr,
mb,
}
enum Net {
ak,
us,
nn,
}
@volatile
private enum Type {
earthquake,
}
@volatile
private enum Status {
reviewed,
}
@volatile
private enum LocationSource {
ak,
us,
nn,
}
@volatile
private enum MagSource {
ak,
us,
nn,
}
fn import_earthquakes() {
if (earthquakes_by_geo.size() > 0) {
return;
}
var reader = CsvReader<Record> {
path: "web-components/gui-map/earthquakes_4.5_month.csv",
format: CsvFormat {
header_lines: 1,
},
};
var record: Record;
while (reader.can_read()) {
record = reader.read();
var earthquake = Earthquake {
location: geo { record.latitude, record.longitude },
time: record.time,
depth: record.depth,
depthError: record.depthError,
mag: record.mag,
magType: record.magType,
nst: record.nst,
gap: record.gap,
dmin: record.dmin,
rms: record.rms,
net: record.net,
id: record.id,
updated: record.updated,
place: record.place,
magError: record.magError,
magNst: record.magNst,
magSource: record.magSource,
};
earthquakes_by_geo.set(earthquake.location, clone(earthquake));
earthquakes_by_time.setAt(earthquake.time, earthquake);
}
info("Imported ${earthquakes_by_geo.size()} eartquakes from ${earthquakes_by_time.firstTime()} to ${earthquakes_by_time.lastTime()}");
}
@expose
fn earthquakes(): Array<Earthquake> {
var arr = Array<Earthquake> {};
arr.set_capacity(earthquakes_by_time.size());
for (_, e in earthquakes_by_time) {
arr.add(e);
}
return arr;
}