5. Display UNL Grid and Cells

Follow the next steps to display the UNL grid lines and cells on the map in the sample JS web application.

Install unl-core#

First, install the unl-core library in order to show the grid lines on the map.

npm install unl-core –save

Import the library to access its methods.

import UnlCore from "unl-core";

Add the UNL Grid#

Create a new method for rendering the grid by adding a new map layer and initializing it with an empty features array.

export const renderGridLines = (map) => {
map.addSource("gridLines", {
type: "geojson",
data: {
type: "FeatureCollection",
features: [],
},
});
map.addLayer({
id: "gridLines",
type: "line",
source: "gridLines",
paint: {
"line-color": "#C0C0C0",
"line-width": 0.5,
},
minzoom: 18,
});
};

Next, call this method when the map gets loaded in the app in index.js.

map.on("style.load", () => {
renderGridLines(map);
});

Then, create a method for calculating and updating the grid lines according to the map's current setting.

export const updateGridLines = (map) => {
const bounds = map.getBounds();
const zoom = map.getZoom();
const unlBounds = {
n: bounds._ne.lat,
e: bounds._ne.lng,
s: bounds._sw.lat,
w: bounds._sw.lng,
};
if (zoom >= 18) {
const gridLines = UnlCore.gridLines(unlBounds);
map.getSource("gridLines").setData({
type: "FeatureCollection",
features: gridLines.map((line) => ({
type: "Feature",
properties: {},
geometry: {
type: "LineString",
coordinates: line,
},
})),
});
}
};

Call this method whenever the map transitions from one view to another in index.js.

map.on("moveend", () => {
updateGridLines(map);
});

Now, when you zoom in on the map at a value higher than 18, you should be able to see the grid.

Add UNL Cells#

Display UNL cells on the map when selecting a location. Firstly, add a method for rendering the cell.

export const renderCell = (map) => {
map.addSource("unlCell", {
type: "geojson",
data: {
type: "Feature",
geometry: {
type: "Polygon",
coordinates: [],
},
},
});
map.addLayer({
id: "unlCell_fill",
type: "fill",
source: "unlCell",
paint: {
"fill-color": "#4C4FCA",
"fill-opacity": 1,
},
});
map.addLayer({
id: "unlCell_line",
type: "line",
source: "unlCell",
paint: {
"line-color": "#4C4FCA",
},
});
};

Then, call the previous method in index.js when the map is loaded for the first time.

map.on("style.load", () => {
renderGridLines(map);
renderCell(map);
});

Add a helper method to transform point coordinates from the map into a geoJSON Position array which contains the bounds of that point (the cell corners) by using the unl-core library.

export const coordinatesToGejsonPositionArray = (coordinates, gridType) => {
const geojsonPositionArray = [];
const geohash = UnlCore.encode(coordinates.lat, coordinates.lng, gridType);
const unlCoreBounds = UnlCore.bounds(geohash);
geojsonPositionArray.push([unlCoreBounds.w, unlCoreBounds.n]);
geojsonPositionArray.push([unlCoreBounds.w, unlCoreBounds.s]);
geojsonPositionArray.push([unlCoreBounds.e, unlCoreBounds.s]);
geojsonPositionArray.push([unlCoreBounds.e, unlCoreBounds.n]);
geojsonPositionArray.push([unlCoreBounds.w, unlCoreBounds.n]);
return [geojsonPositionArray];
};

Next, create a method to update the rendered cell according to the selected location on the map.

export const updateCell = (map, coordinates, event) => {
let features = [];
if (event) {
features = map.queryRenderedFeatures(event.point);
}
map.getSource("unlCell").setData({
type: "Feature",
geometry: {
type: "Polygon",
coordinates: coordinatesToGejsonPositionArray(coordinates, 9),
},
properties: features[0] ? features[0].properties : {},
});
map.flyTo({
center: coordinates,
zoom: map.getZoom() < 18 ? 18 : map.getZoom(),
});
};

Call the updateCell method whenever a click event is captured on the map.

map.on("click", (event) => {
updateCell(map, event.lngLat, event);
});

A cell should be visible whenever you click somewhere on the map.

Integrate an Action Menu#

Add a new menu component in the application in order to allow the selection of different scenarios, such as creating and importing POIs.

Firstly, add a new <div> in the index.html file.

<div id="action-sheet" class="action-sheet"></div>

Then, add styling for the new action sheet component.

.action-sheet {
position: absolute;
display: flex;
flex-direction: column;
align-items: center;
z-index: 1;
background-color: white;
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);
left: 20px;
top: 20px;
width: 380px;
height: 600px;
}
.action-sheet-content {
display: flex;
flex-direction: column;
align-items: stretch;
}

Create the new menu component (we named it ActionSheet.js).

const ActionSheet = () => {
const template = `
<p class="title">UNL SDK Tutorials<p/>
<div class="action-sheet-content">
</div>
`;
return template;
};
export default ActionSheet;

Finally, initialize the component in the index.js file.

document.getElementById("action-sheet").innerHTML = ActionSheet();
};
export default ActionSheet;

At this point, the action sheet should be visible in the app.