---
title: "useLayerTree"
description: "Read a map's layer tree to build your own layer panel, with reads and writes going back to each layer group's v-model."
canonical_url: "https://maplibre.mhaibaraai.cn/en/docs/composables/use-layer-tree"
---
# useLayerTree

> Read a map's layer tree to build your own layer panel, with reads and writes going back to each layer group's v-model.

## Introduction

`useLayerTree` returns every [`MaplibreLayerGroup`](https://maplibre.mhaibaraai.cn/docs/core/layer-group) with a `title` on the map, in declaration order. Each item's `setVisible` and `setOpacity` write back to that group's `v-model`, so a custom panel stays in sync with [MaplibreLayerControl](https://maplibre.mhaibaraai.cn/docs/controls/layer-control) and [MaplibreLegend](https://maplibre.mhaibaraai.cn/docs/controls/legend). It suits layer panels placed in an app sidebar and built with a component library such as Nuxt UI.

> [!NOTE]
> 
> Outside the 
> 
> <MaplibreMap>
> 
>  subtree, pass the target map through 
> 
> options.mapId
> 
>  and set 
> 
> map-id
> 
>  on that map.

## Usage

A layer panel built with `USwitch` and `USlider` on the right:

```vue [UseLayerTreeExample.vue]
<script setup lang="ts">
import type { FeatureCollection } from 'geojson'

const mapId = 'use-layer-tree-demo'
// 地图子树外通过 mapId 读取图层树
const tree = useLayerTree({ mapId })

const zone: FeatureCollection = {
  type: 'FeatureCollection',
  features: [{ type: 'Feature', properties: {}, geometry: { type: 'Polygon', coordinates: [[[116.36, 39.95], [116.44, 39.95], [116.44, 39.89], [116.36, 39.89], [116.36, 39.95]]] } }]
}
const river: FeatureCollection = {
  type: 'FeatureCollection',
  features: [{ type: 'Feature', properties: {}, geometry: { type: 'LineString', coordinates: [[116.33, 39.93], [116.39, 39.91], [116.47, 39.92]] } }]
}
</script>

<template>
  <div class="grid h-115 w-full grid-cols-[1fr_12rem] overflow-hidden rounded-(--ui-radius) border border-default">
    <MaplibreMap :map-id="mapId" :options="{ style: 'https://tiles.openfreemap.org/styles/positron', center: [116.4, 39.92], zoom: 11 }">
      <MaplibreLayerGroup title="规划片区">
        <MaplibreLayer layer-id="tree-zone" type="fill" :source="{ type: 'geojson', data: zone }" :paint="{ 'fill-color': '#f59e0b', 'fill-opacity': 0.4 }" />
      </MaplibreLayerGroup>
      <MaplibreLayerGroup title="河流">
        <MaplibreLayer layer-id="tree-river" type="line" :source="{ type: 'geojson', data: river }" :paint="{ 'line-color': '#0ea5e9', 'line-width': 4 }" />
      </MaplibreLayerGroup>
    </MaplibreMap>
    <aside class="flex flex-col gap-3 border-l border-default p-3">
      <div v-for="item in tree" :key="item.id" class="flex flex-col gap-1">
        <USwitch :model-value="item.visible" :label="item.title" size="sm" @update:model-value="item.setVisible($event)" />
        <USlider
          :model-value="item.opacity"
          :min="0"
          :max="1"
          :step="0.05"
          size="sm"
          :disabled="!item.visible"
          @update:model-value="item.setOpacity($event ?? 1)"
        />
      </div>
    </aside>
  </div>
</template>
```

## API

### `useLayerTree()`

**options.mapId** (`string`): Target map id; required outside the <MaplibreMap> subtree.

Returns `ComputedRef<LayerTreeItem[]>`, where each item contains:

**id** (`string`): Unique id of the group.

**title** (`string`): Group title.

**visible** (`boolean`): The group's own visibility switch.

**opacity** (`number`): The group's own opacity, 0..1.

**legend** (`LegendItem[]`): Legend items, from the legend prop or derived from child layer colors.

**setVisible** (`(visible: boolean) => void`): Writes back to the group's v-model:visible.

**setOpacity** (`(opacity: number) => void`): Writes back to the group's v-model:opacity; values outside 0..1 are clamped.

## Changelog

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


## Sitemap

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