Skip to content

Commit

Permalink
feat(scale): Add Imperial to map info bar (Canadian-Geospatial-Platfo…
Browse files Browse the repository at this point in the history
…rm#2612)

* feat(scale): Add Imperial to map info bar
Closes Canadian-Geospatial-Platform#2544

* fix perfomance
  • Loading branch information
jolevesq authored Nov 22, 2024
1 parent d05e59b commit e667188
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 83 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,22 @@ export class MapEventProcessor extends AbstractEventProcessor {
const store = getGeoViewStore(mapId);

// add map controls (scale)
const scaleBar = new ScaleLine({
const scaleBarMetric = new ScaleLine({
units: 'metric',
target: document.getElementById(`${mapId}-scaleControlBar`) as HTMLElement,
target: document.getElementById(`${mapId}-scaleControlBarMetric`) as HTMLElement,
bar: true,
text: true,
});

const scaleLine = new ScaleLine({
units: 'metric',
target: document.getElementById(`${mapId}-scaleControlLine`) as HTMLElement,
const scaleBarImperial = new ScaleLine({
units: 'imperial',
target: document.getElementById(`${mapId}-scaleControlBarImperial`) as HTMLElement,
bar: true,
text: true,
});
map.addControl(scaleLine);
map.addControl(scaleBar);

map.addControl(scaleBarMetric);
map.addControl(scaleBarImperial);

// add map overlays
// create overlay for north pole icon
Expand Down Expand Up @@ -265,8 +268,8 @@ export class MapEventProcessor extends AbstractEventProcessor {
// Check if the scaleControl exists and is showing information, wait for it
await whenThisThen(
() =>
document.getElementById(`${mapId}-scaleControlLine`)?.querySelector('.ol-scale-line-inner') &&
document.getElementById(`${mapId}-scaleControlBar`)?.querySelector('.ol-scale-text')
document.getElementById(`${mapId}-scaleControlBarMetric`)?.querySelector('.ol-scale-text') &&
document.getElementById(`${mapId}-scaleControlBarImperial`)?.querySelector('.ol-scale-text')
);
} catch (error) {
// Log
Expand All @@ -275,16 +278,20 @@ export class MapEventProcessor extends AbstractEventProcessor {
// throw error;
}

const scaleControlLineInnerElement = document
.getElementById(`${mapId}-scaleControlLine`)
?.querySelector('.ol-scale-line-inner') as HTMLElement;
const lineWidth = scaleControlLineInnerElement?.style.width;
const labelGraphic = scaleControlLineInnerElement?.innerHTML;
// Get metric values
const scaleControlBarMetric = document.getElementById(`${mapId}-scaleControlBarMetric`);
const lineWidthMetric = (scaleControlBarMetric?.querySelector('.ol-scale-bar-inner') as HTMLElement)?.style.width;
const labelGraphicMetric = (scaleControlBarMetric?.querySelector('.ol-scale-bar-inner')!.lastChild as HTMLElement)?.innerHTML;

// Get metric values
const scaleControlBarImperial = document.getElementById(`${mapId}-scaleControlBarImperial`);
const lineWidthImperial = (scaleControlBarImperial?.querySelector('.ol-scale-bar-inner') as HTMLElement)?.style.width;
const labelGraphicImperial = (scaleControlBarImperial?.querySelector('.ol-scale-bar-inner')!.lastChild as HTMLElement)?.innerHTML;

const scaleControlBarInnerElement = document.getElementById(`${mapId}-scaleControlBar`)?.querySelector('.ol-scale-text') as HTMLElement;
const labelNumeric = scaleControlBarInnerElement?.innerHTML;
// get resolution value (same for metric and imperial)
const labelNumeric = (scaleControlBarMetric?.querySelector('.ol-scale-text') as HTMLElement)?.innerHTML;

return { lineWidth, labelGraphic, labelNumeric };
return { lineWidthMetric, labelGraphicMetric, lineWidthImperial, labelGraphicImperial, labelNumeric };
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,9 +179,9 @@ export default function ExportModal(): JSX.Element {
</Box>
<Box display="flex" justifyContent="space-between" alignItems="center" sx={{ padding: '1rem', paddingBottom: 0 }}>
<Box>
{!!scale.labelGraphic.length && (
{!!scale.labelGraphicMetric && (
<Box>
{scale.labelGraphic} {t('exportModal.approx')} <hr />
{scale.labelGraphicMetric} {t('exportModal.approx')} <hr />
</Box>
)}
</Box>
Expand Down
146 changes: 85 additions & 61 deletions packages/geoview-core/src/core/components/scale/scale.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useState } from 'react';
import { useState, useCallback, useMemo } from 'react';

import { useTranslation } from 'react-i18next';

Expand Down Expand Up @@ -41,75 +41,99 @@ export function Scale(): JSX.Element {
const scale = useMapScale();
const interaction = useMapInteraction();

/**
* Switch the scale mode
*/
const switchScale = (): void => {
setScaleMode((scaleMode + 1) % 2);
};

// set the scales values array
const scaleValues: TypeScale[] = [
{
scaleId: '0',
label: scale.labelGraphic,
borderBottom: true,
},
{
scaleId: '1',
label: scale.labelNumeric,
borderBottom: false,
// Memoize scale values array since it doesn't change
const scaleValues: TypeScale[] = useMemo(
() => [
{
scaleId: '0',
label: scale.labelGraphicMetric,
borderBottom: true,
},
{
scaleId: '1',
label: scale.labelGraphicImperial,
borderBottom: true,
},
{
scaleId: '2',
label: scale.labelNumeric,
borderBottom: false,
},
],
[scale.labelGraphicMetric, scale.labelGraphicImperial, scale.labelNumeric]
);

// Memoize getScaleWidth function
const getScaleWidth = useCallback(
(mode: number): string => {
if (mode === 0) return scale.lineWidthMetric;
if (mode === 1) return scale.lineWidthImperial;
return 'none';
},
];
[scale.lineWidthMetric, scale.lineWidthImperial]
);

return (
<Tooltip title={t('mapnav.scale')!} placement="top">
<Box sx={{ minWidth: 120 }}>
<Box id={`${mapId}-scaleControlBar`} sx={sxClasses.scaleControl} />
<Box id={`${mapId}-scaleControlLine`} sx={sxClasses.scaleControl} />
<Button
onClick={() => switchScale()}
type="text"
sx={sxClasses.scaleContainer}
disableRipple
className={`interaction-${interaction}`}
>
{expanded ? (
<Box sx={sxClasses.scaleExpandedContainer}>
{scaleValues.map((value, index) => {
return (
<Box sx={sxClasses.scaleExpandedCheckmarkText} key={value.scaleId}>
<CheckIcon
sx={{ ...sxClasses.scaleCheckmark, fontSize: theme.palette.geoViewFontSize.lg, opacity: scaleMode === index ? 1 : 0 }}
/>
<Box
component="span"
className={`${index === 0 ? 'hasScaleLine' : ''}`}
sx={{
...sxClasses.scaleText,
borderBottom: !value.borderBottom ? 'none' : '1px solid',
width: scaleValues[scaleMode].borderBottom ? scale.lineWidth : 'none',
}}
>
{value.label}
</Box>
</Box>
);
})}
</Box>
) : (
// Memoize switchScale callback
const switchScale = useCallback((): void => {
setScaleMode((prev) => (prev + 1) % 3);
}, []);

// Memoize the expanded content
const expandedContent = useMemo(
() => (
<Box sx={sxClasses.scaleExpandedContainer}>
{scaleValues.map((value, index) => (
<Box sx={sxClasses.scaleExpandedCheckmarkText} key={value.scaleId}>
<CheckIcon
sx={{
...sxClasses.scaleCheckmark,
fontSize: theme.palette.geoViewFontSize.lg,
opacity: scaleMode === index ? 1 : 0,
}}
/>
<Box
component="span"
className={`interaction-${interaction} ${scaleValues[scaleMode].borderBottom ? 'hasScaleLine' : ''}`}
className={index === 2 ? '' : 'hasScaleLine'}
sx={{
...sxClasses.scaleText,
borderBottom: !scaleValues[scaleMode].borderBottom ? 'none' : '1px solid',
width: scaleValues[scaleMode].borderBottom ? scale.lineWidth : 'none',
borderBottom: value.borderBottom ? '1px solid' : 'none',
width: value.borderBottom ? getScaleWidth(index) : 'none',
}}
>
{scaleValues[scaleMode].label}
{value.label}
</Box>
)}
</Box>
))}
</Box>
),
[scaleValues, scaleMode, sxClasses, theme.palette.geoViewFontSize.lg, getScaleWidth]
);

// Memoize the collapsed content
const collapsedContent = useMemo(
() => (
<Box
component="span"
className={`interaction-${interaction} ${scaleValues[scaleMode].borderBottom ? 'hasScaleLine' : ''}`}
sx={{
...sxClasses.scaleText,
borderBottom: scaleValues[scaleMode].borderBottom ? '1px solid' : 'none',
width: scaleValues[scaleMode].borderBottom ? getScaleWidth(scaleMode) : 'none',
}}
>
{scaleValues[scaleMode].label}
</Box>
),
[interaction, scaleValues, scaleMode, sxClasses.scaleText, getScaleWidth]
);

return (
<Tooltip title={t('mapnav.scale')!} placement="top">
<Box sx={{ minWidth: 120 }}>
<Box id={`${mapId}-scaleControlBarMetric`} sx={sxClasses.scaleControl} />
<Box id={`${mapId}-scaleControlBarImperial`} sx={sxClasses.scaleControl} />
<Button onClick={switchScale} type="text" sx={sxClasses.scaleContainer} disableRipple className={`interaction-${interaction}`}>
{expanded ? expandedContent : collapsedContent}
</Button>
</Box>
</Tooltip>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,13 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt
pointerPosition: undefined,
pointMarkers: {},
rotation: 0,
scale: { lineWidth: '', labelGraphic: '', labelNumeric: '' } as TypeScaleInfo,
scale: {
lineWidthMetric: '',
labelGraphicMetric: '',
lineWidthImperial: '',
labelGraphicImperial: '',
labelNumeric: '',
} as TypeScaleInfo,
size: [0, 0] as [number, number],
visibleLayers: [],
zoom: 0,
Expand Down Expand Up @@ -844,8 +850,10 @@ export function initializeMapState(set: TypeSetStore, get: TypeGetStore): IMapSt
}

export interface TypeScaleInfo {
lineWidth: string;
labelGraphic: string;
lineWidthMetric: string;
labelGraphicMetric: string;
lineWidthImperial: string;
labelGraphicImperial: string;
labelNumeric: string;
}

Expand Down

0 comments on commit e667188

Please sign in to comment.