ExB Dev 1.13. Here is the widget.tsx code for a custom widget that restricts the map view
/**
Licensing
Copyright 2022 Esri
Modified from 'map-view' sample code widget (JR, YH)
Map view widget that will restrict the map view to the minZoomScale specified and restrict panning to the original extent of the map
*/
import { React, jimuHistory, DataSourceComponent, type AllWidgetProps, type IMState, type IMUrlParameters } from 'jimu-core'
import MapView from 'esri/views/MapView'
import type WebMap from 'esri/WebMap'
import Extent from 'esri/geometry/Extent'
import Point from "@arcgis/core/geometry/Point.js";
import { MapViewManager, type WebMapDataSource } from 'jimu-arcgis'
// Bring the 'Home' and 'Scalebar' properties into the map
import Home from '@arcgis/core/widgets/Home';
import ScaleBar from '@arcgis/core/widgets/ScaleBar';
import Popup from "@arcgis/core/widgets/Popup.js";
// Alert component state
interface State {
isValidCenter: boolean;
}
// Not sure what the following does from the sample 'map-view' widget from which this code was modified queries the URL REST parameters for a mapview extent
interface ExtraProps {
queryObject: IMUrlParameters
}
// Set a minimum zoom scale to prevent user from zooming out beyond the valid extent
const minZoomScale = 6
export default class Widget extends React.PureComponent<AllWidgetProps<unknown> & ExtraProps, State> {
mapContainer = React.createRef<HTMLDivElement>()
mapView: MapView
webMap: WebMap
extentWatch: __esri.WatchHandle
mvManager: MapViewManager = MapViewManager.getInstance();
constructor(props) {
super(props);
this.state = {
isValidCenter: true, // Initialize state with default value
};
}
static mapExtraStateProps = (state: IMState): ExtraProps => {
return {
queryObject: state.queryObject
}
}
onDsCreated = (webmapDs: WebMapDataSource) => {
console.log("Webmap loaded")
if (!webmapDs) {
console.log("Webmap not initialized")
return
}
if (!this.mvManager.getJimuMapViewById(this.props.id)) {
const options: __esri.MapViewProperties = {
map: webmapDs.map,
container: this.mapContainer.current,
constraints:{
minZoom: minZoomScale,
snapToZoom: false
}
}
console.log("minZoom set:", minZoomScale)
this.mvManager.createJimuMapView({
mapWidgetId: this.props.id,
view: new MapView(options),
dataSourceId: webmapDs.id,
isActive: true,
mapViewManager: this.mvManager
}).then(jimuMapView => {
// Create and add the Home widget to the map view
const homeWidget = new Home({ view: jimuMapView.view });
jimuMapView.view.ui.add(homeWidget, 'top-left');
// Need to explictly cast the view to --esri.MapViewProperties
// to ensure type compatibility with the scalebar
const mapView = jimuMapView.view as __esri.MapViewProperties;
// Create and add the Scalebar widget to the map view
const scaleBarWidget = new ScaleBar({ view: mapView });
jimuMapView.view.ui.add(scaleBarWidget,'bottom-left')
//console.log(mapView.extent)
const view = jimuMapView.view as __esri.MapView;
const extentLimit = view.extent.clone();
view.constraints.geometry = extentLimit
})
}
}
mapNode = <div className="widget-map" style={{ width: '100%', height: '100%' }} ref={this.mapContainer}></div>
render () {
if (!this.props.useDataSources || this.props.useDataSources.length === 0) {
return 'Select a webmap in the settings panel'
}
return <DataSourceComponent useDataSource={this.props.useDataSources[0]} onDataSourceCreated={this.onDsCreated}>
{this.mapNode}
</DataSourceComponent>
}
}