Skip to content

Source Navigation

Source Navigation

Cette page est générée automatiquement à partir du dépôt local au moment de la génération de la documentation.

Fichiers inclus

packages/common/src/lib/widgets/navigation/navigation.declaration.ts

packages/common/src/lib/widgets/navigation/navigation.declaration.ts
import { widgetFactorySvelte, type WidgetProps } from '$lib/api/managers/widget';
import { type NavigationConfig, navigationConfigSchema } from './navigation.config';
import type { WidgetDeclaration } from '$lib/api/managers/widget/widget-declaration';
export const declaration = {
factory: () => import('./Navigation.svelte').then((Navigation) => widgetFactorySvelte(Navigation)),
schema: () => navigationConfigSchema,
} satisfies WidgetDeclaration;
export type NavigationProps = WidgetProps<NavigationConfig>;

packages/common/src/lib/widgets/navigation/navigation.config.ts

packages/common/src/lib/widgets/navigation/navigation.config.ts
import { iconSchema } from '$lib/api/icons';
import { defineWidgetConfig } from '$lib/api/managers/configuration';
import { inToolbarSchemaFrom } from '$lib/api/managers/configuration/models/widget/widget-in-toolbar.schema';
import { extentSchema } from '$lib/api/domain/api-extent.schema';
import { BELGIUM_EXTENT } from '$lib/api/domain/api-extent.utils';
import { z } from 'zod';
const fullZoomSchema = z
.object({
label: z.string().default('Afficher toute la Belgique'),
extent: extentSchema.default(BELGIUM_EXTENT),
})
.prefault({});
const scaleStepSchema = z.object({
minScale: z.number().optional(),
maxScale: z.number().optional(),
label: z.string(),
});
const scaleStepsSchema = z.array(scaleStepSchema).default([
{
maxScale: 500,
label: 'Maison',
},
{
minScale: 501,
maxScale: 2500,
label: 'Rue',
},
{
minScale: 2501,
maxScale: 15000,
label: 'Quartier',
},
{
minScale: 15001,
maxScale: 50000,
label: 'Commune',
},
{
minScale: 50001,
maxScale: 100000,
label: 'Arrondissement',
},
{
minScale: 100001,
maxScale: 500000,
label: 'Province',
},
{
minScale: 500001,
maxScale: 1200000,
label: 'Région',
},
{
minScale: 1200001,
label: 'Pays',
},
]);
export const navigationConfigSchema = defineWidgetConfig({
inToolbar: inToolbarSchemaFrom(false),
config: z
.object({
scales: scaleStepsSchema,
displayScaleLabels: z.boolean().default(true),
fullZoom: fullZoomSchema,
displayFullZoom: z.boolean().default(true),
fullZoomIcon: iconSchema.optional(),
})
.prefault({}),
});
export type ScaleStep = z.infer<typeof scaleStepSchema>;
export type NavigationConfig = z.infer<typeof navigationConfigSchema>;

packages/common/src/lib/widgets/navigation/Navigation.svelte

packages/common/src/lib/widgets/navigation/Navigation.svelte
<!--Helpful to understand zoom and scale management of esri : https://developers.arcgis.com/javascript/latest/api-reference/esri-views-MapView.html#mapview-lods-->
<script lang="ts">
import { Button } from '$lib/components/shadcn/ui/button';
import type { ScaleStep } from './navigation.config';
import { onDestroy } from 'svelte';
import { getMapManager } from '$lib/api/map';
import Globe from 'lucide-svelte/icons/globe';
import Icon from '$lib/components/icon/Icon.svelte';
import type { NavigationProps } from './navigation.declaration';
let { fullConfig }: NavigationProps = $props();
const { config } = fullConfig;
const mapManager = getMapManager();
const scaleTool = mapManager.tools.scale;
const zoomTool = mapManager.tools.zoom;
let sliderValue: number | undefined = $state();
const scales: ScaleStep[] = config.scales;
let currentStep: ScaleStep | undefined = $derived(scales[sliderValue!]);
const sliderMaxValue = scales.length - 1;
const scaleWatchUnsubscriber = mapManager.tools.events.watch(
'SCALE',
(scale) => {
sliderValue = scales.findIndex(
(scaleStep) =>
(!scaleStep.minScale || scaleStep.minScale <= scale) &&
(!scaleStep.maxScale || scaleStep.maxScale >= scale),
);
},
{ initial: true },
);
function updateMap() {
if (!currentStep) return;
if (currentStep.minScale && currentStep.maxScale) {
scaleTool.setScale((currentStep.minScale + currentStep.maxScale) / 2);
} else {
scaleTool.setScale(currentStep.minScale ?? currentStep.maxScale ?? 0);
}
}
function zoomToFullExtent() {
zoomTool.zoomToExtent(config.fullZoom.extent);
}
onDestroy(() => scaleWatchUnsubscriber());
</script>
<!-- Style à adapter quand tailwind sera mergé -->
<div>
<div>{currentStep?.label}</div>
<div class="flex gap-2">
<input
class="slider"
type="range"
bind:value={sliderValue}
onchange={updateMap}
min="0"
max={sliderMaxValue}
step="1"
/>
{#if config.displayFullZoom}
<Button
variant={'outline'}
class="full-zoom-button gv-rounded-full gv-p-0 gv-size-5 gv-overflow-hidden"
onclick={zoomToFullExtent}
title={config.fullZoom.label}
>
<Icon icon={config.fullZoomIcon} alt="Icon fullscreen">
<Globe class="gv-size-full" />
</Icon>
</Button>
{/if}
</div>
</div>
<style>
.slider {
width: var(--gv-navigation-slider-width, 200px);
}
</style>

Aller plus loin