Skip to content

Commit

Permalink
feat: add distance and area measurement tools
Browse files Browse the repository at this point in the history
Closes #700
  • Loading branch information
stdavis committed Nov 27, 2024
1 parent 546a731 commit 536ae02
Show file tree
Hide file tree
Showing 5 changed files with 115 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@
"OPENRELEASE",
"opensgid",
"OPENTANK",
"opentype",
"osgeo",
"overscan",
"packagejson",
Expand Down Expand Up @@ -151,6 +152,7 @@
"testdata",
"tooele",
"toolbelt",
"topbar",
"tseslint",
"TSQL",
"ujson",
Expand Down
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@
},
"dependencies": {
"@arcgis/core": "^4.30.9",
"@esri/calcite-components-react": "^2.13.2",
"@radix-ui/react-accessible-icon": "^1.1.0",
"@radix-ui/react-accordion": "^1.2.1",
"@radix-ui/react-checkbox": "^1.1.2",
Expand Down
2 changes: 2 additions & 0 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
DialogContent,
DialogTitle,
} from './utah-design-system/Dialog.jsx';
import MeasureTools from './components/MeasureTools';

function App() {
useEffect(() => {
Expand Down Expand Up @@ -67,6 +68,7 @@ function App() {
<div className="flex h-full w-full flex-col md:flex-row">
<MapProvider>
<div className="relative flex flex-1 flex-col items-center border-b border-slate-300 md:border-r">
<MeasureTools />
<MapComponent />
<ResultsPanel />
</div>
Expand Down
96 changes: 96 additions & 0 deletions src/components/MeasureTools.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import '@esri/calcite-components/dist/components/calcite-icon';
import { useEffect, useRef, useState } from 'react';
import useMap from '../contexts/useMap';
import AreaMeasurement2D from '@arcgis/core/widgets/AreaMeasurement2D';
import DistanceMeasurement2D from '@arcgis/core/widgets/DistanceMeasurement2D';
import Measurement from '@arcgis/core/widgets/Measurement';
import { twMerge } from 'tailwind-merge';
import { CalciteIcon } from '@esri/calcite-components-react';

export default function MeasureTools() {
const { mapView } = useMap();

const distanceMeasurement2D = useRef<DistanceMeasurement2D>(null);
const areaMeasurement2D = useRef<AreaMeasurement2D>(null);
const measurement = useRef<Measurement>(null);
const drawingToolbarRef = useRef<HTMLDivElement>(null);

const [activeTool, setActiveTool] = useState<'distance' | 'area' | null>(
null,
);

useEffect(() => {
if (!mapView) return;

distanceMeasurement2D.current = new DistanceMeasurement2D({
view: mapView,
visible: false,
});
areaMeasurement2D.current = new AreaMeasurement2D({
view: mapView,
visible: false,
});
measurement.current = new Measurement();

mapView.when(() => {
mapView.ui.add(drawingToolbarRef.current, 'top-left');
mapView.ui.add(measurement.current, 'bottom-right');
measurement.current.view = mapView;
});
}, [mapView]);

const onDistanceButtonClick = (event) => {
const toolName = 'distance';
measurement.current.activeTool = toolName;
setActiveTool(toolName);
event.target.classList.add('active');
};

const onAreaButtonClick = (event) => {
const toolName = 'area';
measurement.current.activeTool = toolName;
setActiveTool(toolName);
event.target.classList.add('active');
};

const onClearButtonClick = () => {
setActiveTool(null);
measurement.current.clear();
};

return (
<div>
<div ref={drawingToolbarRef} className="esri-component esri-widget">
<button
className={twMerge([
'esri-widget--button esri-interactive',
activeTool === 'area' && 'bg-slate-200',
])}
onClick={onAreaButtonClick}
type="button"
title="Measure area"
>
<CalciteIcon icon="measure-area" scale="s" />
</button>
<button
className={twMerge([
'esri-widget--button esri-interactive',
activeTool === 'distance' && 'bg-slate-200',
])}
onClick={onDistanceButtonClick}
type="button"
title="Measure distance between two or more points"
>
<CalciteIcon icon="measure" scale="s" />
</button>
<button
className="esri-widget--button esri-interactive"
title="Clear Measurements"
onClick={onClearButtonClick}
>
<CalciteIcon icon="trash" scale="s" />
</button>
</div>
</div>
);
}

0 comments on commit 536ae02

Please sign in to comment.