Restrict the map view area
vanilla.html
common.ts
react.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<script crossorigin src="https://cdn.jsdelivr.net/npm/@turf/turf@6/turf.min.js"></script>
<script crossorigin src="https://unpkg.com/@babel/standalone@7/babel.min.js"></script>
<!-- To make the map appear, you must add your apikey -->
<script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>
<script
data-plugins="transform-modules-umd"
data-presets="typescript"
type="text/babel"
src="./common.ts"
></script>
<script data-plugins="transform-modules-umd" data-presets="typescript" type="text/babel">
import {
BIG_RESTRICT_AREA,
LITTLE_RESTRICT_AREA,
BIG_ZOOM_RANGE,
LITTLE_ZOOM_RANGE,
boundsToPolygonCoordinates
} from './common';
window.map = null;
main();
async function main() {
// Waiting for all api elements to be loaded
await mappable.ready;
const {MMap, MMapDefaultSchemeLayer, MMapDefaultFeaturesLayer, MMapFeature, MMapControls, MMapControlButton} =
mappable;
// Initialize the map
map = new MMap(
// Pass the link to the HTMLElement of the container
document.getElementById('app'),
// Pass the map initialization parameters, set the map location bounds with the current restricted area
{
location: {bounds: LITTLE_RESTRICT_AREA},
restrictMapArea: LITTLE_RESTRICT_AREA,
zoomRange: LITTLE_ZOOM_RANGE
},
// Add a map schema layer and a geo objects layer
[new MMapDefaultSchemeLayer({}), new MMapDefaultFeaturesLayer({})]
);
// Create and add a polygon to the map that will mark the border of the map restrict area
const borderPolygon = new MMapFeature({
id: 'polygon',
geometry: {
type: 'Polygon',
coordinates: [boundsToPolygonCoordinates(LITTLE_RESTRICT_AREA)]
},
style: {
stroke: [{width: 12, color: '#007afce6'}],
fill: 'rgba(0, 0, 0, 0)'
}
});
map.addChild(borderPolygon);
// Add a container for MMapControlButton and add it to the map
const controls = new MMapControls({position: 'bottom'});
map.addChild(controls);
// Flag to increase/decrease the restricted area on the map
let isBigRestrictArea = false;
function changeViewFieldBtnHandler() {
isBigRestrictArea = !isBigRestrictArea;
// The selection of the restricted area and other map parameters depends on the flag's value
const currentRestrictArea = isBigRestrictArea ? BIG_RESTRICT_AREA : LITTLE_RESTRICT_AREA;
const currentZoomRange = isBigRestrictArea ? BIG_ZOOM_RANGE : LITTLE_ZOOM_RANGE;
const currentBtnText = isBigRestrictArea ? 'Decrease The Field Of View' : 'Increase The Field Of View';
// Update the map with the current restricted area and zoom range
map.update({
restrictMapArea: currentRestrictArea,
zoomRange: currentZoomRange
});
// Update the map location bounds with the current restricted area
map.update({location: {bounds: currentRestrictArea}});
// Update the border polygon coordinates depending on the current restricted area
borderPolygon.update({
geometry: {
type: 'Polygon',
coordinates: [boundsToPolygonCoordinates(currentRestrictArea)]
}
});
changeViewFieldBtn.update({text: currentBtnText});
}
// Add MMapControlButton that changes the restricted area
const changeViewFieldBtn = new MMapControlButton({
text: 'Increase The Field Of View',
color: '#fff',
background: '#007afce6',
onClick: changeViewFieldBtnHandler
});
controls.addChild(changeViewFieldBtn);
}
</script>
<!-- prettier-ignore -->
<style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; } </style>
</head>
<body>
<div id="app"></div>
</body>
</html>
import type {ZoomRange, LngLatBounds, LngLat} from '@mappable-world/mappable-types';
export const LITTLE_ZOOM_RANGE: ZoomRange = {min: 14, max: 20};
export const BIG_ZOOM_RANGE: ZoomRange = {min: 7, max: 14};
// Bounding box - bottom left and top right corners
export const LITTLE_RESTRICT_AREA: LngLatBounds = [
[55.34271, 25.19559],
[55.54271, 25.29559]
];
export const BIG_RESTRICT_AREA: LngLatBounds = [
[44.11771, 16.51259],
[66.09971, 33.94659]
];
// From the coordinates of bottom left and top right corners, we make 4 coordinates of the rectangle
export function boundsToPolygonCoordinates(bounds: LngLatBounds): LngLat[] {
return [bounds[0], [bounds[1][0], bounds[0][1]], bounds[1], [bounds[0][0], bounds[1][1]]];
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1" />
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<script crossorigin src="https://unpkg.com/@babel/standalone@7/babel.min.js"></script>
<!-- To make the map appear, you must add your apikey -->
<script src="https://js.api.mappable.world/v3/?apikey=<YOUR_APIKEY>&lang=en_US" type="text/javascript"></script>
<script
data-plugins="transform-modules-umd"
data-presets="react, typescript"
type="text/babel"
src="./common.ts"
></script>
<script data-plugins="transform-modules-umd" data-presets="react, typescript" type="text/babel">
import {
BIG_RESTRICT_AREA,
LITTLE_RESTRICT_AREA,
BIG_ZOOM_RANGE,
LITTLE_ZOOM_RANGE,
boundsToPolygonCoordinates
} from './common';
window.map = null;
main();
async function main() {
// For each object in the JS API, there is a React counterpart
// To use the React version of the API, include the module @mappable-world/mappable-reactify
const [mappableReact] = await Promise.all([
mappable.import('@mappable-world/mappable-reactify'),
mappable.ready
]);
const reactify = mappableReact.reactify.bindTo(React, ReactDOM);
const {MMap, MMapDefaultSchemeLayer, MMapDefaultFeaturesLayer, MMapFeature, MMapControls, MMapControlButton} =
reactify.module(mappable);
const {useState, useCallback} = React;
function App() {
// Flag to increase/decrease the restricted area on the map
const [isBigRestrictArea, setIsBigRestrictArea] = useState(false);
// Define states for map parameters
const [restrictArea, setRestrictArea] = useState(LITTLE_RESTRICT_AREA);
const [zoomRange, setZoomRange] = useState(LITTLE_ZOOM_RANGE);
const [btnText, setBtnText] = useState('Increase The Field Of View');
const changeViewFieldBtnHandler = useCallback(() => {
const syncIsBigRestrictArea = !isBigRestrictArea;
setIsBigRestrictArea((prevState) => !prevState);
// The selection of the restricted area and other map parameters depends on the flag's value
const currentRestrictArea = syncIsBigRestrictArea ? BIG_RESTRICT_AREA : LITTLE_RESTRICT_AREA;
const currentZoomRange = syncIsBigRestrictArea ? BIG_ZOOM_RANGE : LITTLE_ZOOM_RANGE;
const currentBtnText = syncIsBigRestrictArea ? 'Reduce The Field Of View' : 'Increase The Field Of View';
// Update the map states with the current restricted area
setRestrictArea(currentRestrictArea);
setZoomRange(currentZoomRange);
setBtnText(currentBtnText);
}, [isBigRestrictArea]);
return (
// Initialize the map and pass initialization parameters, set the map location bounds with the current restricted area
<MMap
location={{bounds: restrictArea}}
restrictMapArea={restrictArea}
zoomRange={zoomRange}
ref={(x) => (map = x)}
>
{/* Add a map schema layer and a geo objects layer */}
<MMapDefaultSchemeLayer />
<MMapDefaultFeaturesLayer />
{/* Add a polygon to the map that will mark the border of the map restrict area */}
<MMapFeature
geometry={{
type: 'Polygon',
coordinates: [boundsToPolygonCoordinates(restrictArea)]
}}
style={{
stroke: [{width: 12, color: '#007afce6'}],
fill: 'rgba(0, 0, 0, 0)'
}}
/>
{/* Add MMapControlButton that changes the restricted area */}
<MMapControls position="bottom">
<MMapControlButton
text={btnText}
color="#fff"
background="#007afce6"
onClick={changeViewFieldBtnHandler}
/>
</MMapControls>
</MMap>
);
}
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('app')
);
}
</script>
<!-- prettier-ignore -->
<style> html, body, #app { width: 100%; height: 100%; margin: 0; padding: 0; font-family: Arial, Helvetica, sans-serif; } .toolbar { position: absolute; z-index: 1000; top: 0; left: 0; display: flex; align-items: center; padding: 16px; } .toolbar a { padding: 16px; } </style>
</head>
<body>
<div id="app"></div>
</body>
</html>