# Layer Zoom Buttons

Layer Zoom buttons allow a user to zoom to a set map extent based on latitude-longitude coordinates. This decreases the time needed to find a specific area through panning, and enhances user-experience.&#x20;

The following steps exemplify how to add Layer Zoom buttons through the creation of a service. See also [how to create a service](https://github.com/open-pioneer/trails-starter/blob/main/docs/tutorials/HowToCreateAService.md) through the OPT documentation.&#x20;

<div align="center"><figure><img src="/files/PAtrDS4flS2OsAlHcdcq" alt="" width="137"><figcaption><p>Layer Zoom buttons</p></figcaption></figure></div>

### Adding Layer Zoom buttons

In this example, we will reference the `LayerZoom.ts` service created in the Copenhagen RWL. See the full service implementation in the repository [here](https://github.com/directedproject-eu/directed-pioneer/blob/main/src/apps/rwl_copenhagen/copenhagen-app/services/LayerZoom.ts).&#x20;

{% stepper %}
{% step %}

#### Import packages for the service&#x20;

For this service, we need the service `runtime` package from OPT, access to the `MapModel`, and `fromLonLat` from OpenLayers.&#x20;

```typescript
// your-app/services/LayerZoom.ts
import { DeclaredService } from "@open-pioneer/runtime";
import { MapModel } from "@open-pioneer/map";
import { fromLonLat } from "ol/proj";
```

{% endstep %}

{% step %}

#### Create an interface

This enables the service to be discoverable by the OPT framework.&#x20;

For example, in this service, we will create five buttons that zoom to areas around the Roskilde Fjord in Denmark.&#x20;

```typescript
// your-app/services/LayerZoom.ts
export interface LayerZoom extends DeclaredService<"app.LayerZoom"> {
    zoomToFrederikssund(mapModel: MapModel): void;
    zoomToEgedal(mapModel: MapModel): void;
    zoomToHalsnaes(mapModel: MapModel): void;
    zoomToLejre(mapModel: MapModel): void;
    zoomToRoskilde(mapModel: MapModel): void;
}
```

{% endstep %}

{% step %}

#### Create a class containing coordinates for each button

```typescript
// your-app/services/LayerZoom.ts
export class LayerZoomImpl implements LayerZoom {
    private MAP_ID = "main";

    zoomToFrederikssund(mapModel: MapModel): void {
        this.zoomToLayer(mapModel, [12.0683, 55.8367], 12);
    }

    zoomToEgedal(mapModel: MapModel): void {
        this.zoomToLayer(mapModel, [12.1839, 55.7689], 12);
    }

    zoomToHalsnaes(mapModel: MapModel): void {
        this.zoomToLayer(mapModel, [11.9489, 55.9706], 12);
    }

    zoomToLejre(mapModel: MapModel): void {
        this.zoomToLayer(mapModel, [11.9435, 55.6048], 12);
    }

    zoomToRoskilde(mapModel: MapModel): void {
        this.zoomToLayer(mapModel, [12.0767, 55.6415], 12);
    }

    private zoomToLayer(mapModel: MapModel, lonLat: [number, number], zoom: number): void {
        const view = mapModel.olMap.getView();
        const center = fromLonLat(lonLat);
        view.animate({ center, zoom, duration: 1000 });
    }
}
```

{% endstep %}

{% step %}

#### Summary working example

We now have a file called `LayerZoom.ts` , which is ready to be registered in the app.&#x20;

See the file [here](https://github.com/directedproject-eu/directed-pioneer/blob/main/src/apps/rwl_copenhagen/copenhagen-app/services/LayerZoom.ts).&#x20;
{% endstep %}

{% step %}

#### Register the service in your app

Now, we need to go to the `build.config.mjs` file. This file should be in the project root, and is where we can register the service in the app.&#x20;

We need to reference the service in the UI as well as in the services.&#x20;

For example:&#x20;

```typescript
// your-app/build.config.mjs
import { defineBuildConfig } from "@open-pioneer/build-support";

export default defineBuildConfig({
    styles: "./app.css",
    i18n: ["en", "de", "da"],
    ui: {
        references: [
            "app.LayerZoom", 
        ]
    },
    services: {
        MainMapProvider: {
            provides: ["map.MapConfigProvider"]
        },
        LayerZoomImpl: {
            provides: ["app.LayerZoom"]
        }, 
    },
    properties: {
        userConfig: {}
    }
});
```

{% endstep %}

{% step %}

#### Add the service to the map

We are now ready to add the service to the map interface. We need to import the service, add a statement to use the service, and finally add it to the UI. We will do these steps next, in the `MapApp.tsx` in the Copenhagen RWL.&#x20;

**Import the Service**

We import the service; we also import some packages from `Chakra` for styling the buttons themselves.&#x20;

```typescript
// your-app/MapApp.tsx
import { LayerZoom } from "./services/LayerZoom";
import { Button, VStack } from "@open-pioneer/chakra-integration";
```

**Add a statement to use the Service**

This statement goes in the `export` function, before the `return` statement.&#x20;

```typescript
// your-app/MapApp.tsx
const zoomService = useService<LayerZoom>("app.LayerZoom");
```

**Add the buttons to the UI**&#x20;

Finally, we can add the buttons themselves in the `return` statement of the `MapApp.tsx` .&#x20;

```typescript
// your-app/MapApp.tsx
<MapAnchor position="bottom-left" horizontalGap={15} verticalGap={60}>
    <VStack align="stretch" spacing={2}>
        <Button
            size="sm"
            onClick={() => zoomService.zoomToEgedal(mapModel.map!)}
        >
            {intl.formatMessage({ id: "zoom_buttons.egedal" })}
        </Button>
        <Button
            size="sm"
            onClick={() => zoomService.zoomToFrederikssund(mapModel.map!)}
        >
            {intl.formatMessage({ id: "zoom_buttons.frederikssund" })}
        </Button>
        <Button
            size="sm"
            onClick={() => zoomService.zoomToHalsnaes(mapModel.map!)}
        >
            {intl.formatMessage({ id: "zoom_buttons.halsnaes" })}
        </Button>
        <Button
            size="sm"
            onClick={() => zoomService.zoomToLejre(mapModel.map!)}
        >
            {intl.formatMessage({ id: "zoom_buttons.lejre" })}
        </Button>
        <Button
            size="sm"
            onClick={() => zoomService.zoomToRoskilde(mapModel.map!)}
        >
            {intl.formatMessage({ id: "zoom_buttons.roskilde" })}
        </Button>
    </VStack>
</MapAnchor>
```

{% endstep %}
{% endstepper %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://directed-eu.gitbook.io/data-fabric-manual/adding-and-developing-features/layer-zoom-buttons.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
