---
title: "useMapSync"
description: "Sync the camera of several maps so moving any one updates the center, zoom, bearing and pitch of the others."
canonical_url: "https://maplibre.mhaibaraai.cn/en/docs/composables/use-map-sync"
---
# useMapSync

> Sync the camera of several maps so moving any one updates the center, zoom, bearing and pitch of the others.

## Introduction

`useMapSync` keeps the cameras of several maps aligned: when any map moves, its `center`, `zoom`, `bearing` and `pitch` are copied to the others. It takes effect once every map instance is ready, aligns the others to the first map in the list at that point, and unbinds automatically when the calling scope is disposed.

> [!NOTE]
> 
> Referencing a map by id requires 
> 
> map-id
> 
>  on that 
> 
> MaplibreMap
> 
> ; maps mounted after the call still work. Use this for two independent maps side by side; for a swipe comparison within one view use 
> 
> MaplibreSwipe
> 
> , which follows the main map one way as its child, so no manual syncing is needed.

## Usage

Two maps side by side stay in sync, and the switch pauses syncing at any time:

```vue [UseMapSyncExample.vue]
<script setup lang="ts">
const enabled = ref(true)

useMapSync(['sync-demo-left', 'sync-demo-right'], { enabled })
</script>

<template>
  <div class="relative grid h-115 w-full grid-cols-2 gap-px overflow-hidden rounded-(--ui-radius) border border-default bg-(--ui-border)">
    <MaplibreMap map-id="sync-demo-left" :options="{ style: 'https://tiles.openfreemap.org/styles/liberty', center: [116.397, 39.908], zoom: 11 }" />
    <MaplibreMap map-id="sync-demo-right" :options="{ center: [116.397, 39.908], zoom: 11 }">
      <MaplibreTiandituLayer layer="img" annotation />
    </MaplibreMap>
    <div class="absolute left-2 top-2 z-10 rounded-md bg-default/90 px-2 py-1 ring ring-default">
      <USwitch v-model="enabled" label="联动" size="sm" />
    </div>
  </div>
</template>
```

## Examples

### Toggle with a button

Either approach can be driven by a button:

- Bind `enabled` to the button state: the maps stay mounted and the toggle only binds or unbinds camera syncing.
- Mount the second map on demand with `v-if`: reference it by `map-id`, and syncing starts once it mounts and stops once it unmounts.

Both approaches align the others to the **first map** in the list when syncing starts, so put the main map first:

```vue
<script setup lang="ts">
const showSide = ref(false)

useMapSync(['main-map', 'side-map'])
</script>

<template>
  <UButton @click="showSide = !showSide">
    Side view
  </UButton>
  <div class="grid h-115" :class="showSide ? 'grid-cols-2' : 'grid-cols-1'">
    <MaplibreMap map-id="main-map" :options="{ style: 'https://tiles.openfreemap.org/styles/liberty' }" />
    <MaplibreMap v-if="showSide" map-id="side-map" :options="{ style: 'https://tiles.openfreemap.org/styles/dark' }" />
  </div>
</template>
```

## API

### `useMapSync()`

**maps** (`MaybeRefOrGetter<MapSyncTarget[]>`) *required*: Maps to sync: map-id strings or map contexts (such as the return value of useMap()); the binding is rebuilt when the list changes.

**options.enabled** (`MaybeRefOrGetter<boolean>`): Whether syncing is enabled, true by default; false unbinds, and turning it back on realigns the others to the first map.

## Changelog

See commit history for [src/runtime/composables/useMapSync.ts](https://github.com/mhaibaraai/movk-maplibre/commits/main/src/runtime/composables/useMapSync.ts).


## Sitemap

See the full [sitemap](https://maplibre.mhaibaraai.cn/sitemap.md) for all pages.
