---
title: "labelPlacements"
description: "给每个节点选一个背离邻居的标签方位，返回节点 key 到方位的映射表。"
canonical_url: "https://sigma.mhaibaraai.cn/docs/utils/label-placements"
---
# labelPlacements

> 给每个节点选一个背离邻居的标签方位，返回节点 key 到方位的映射表。

## 用法

标签放在哪一侧不该是固定的：节点连线最密的方向，也是最容易压到边和邻居标签的方向。把邻居的单位向量加起来取反，就是最空的一侧：

```vue [LabelPlacementsExample.vue]
<script setup lang="ts">
import Graph from 'graphology'
import type { SerializedGraph } from 'graphology-types'
import type { LabelPosition } from 'sigma/types'
import type { SigmaStyles } from '@movk/sigma'

const { data } = await useFetch('/api/data.json')

const payload = data.value as unknown as SerializedGraph
const graph = new Graph(payload.options)
graph.import(payload)

const styles: SigmaStyles = {
  nodes: {
    labelPosition: { attribute: 'labelPlacement', defaultValue: 'below' },
    labelSize: 12
  }
}

const derived = shallowRef(false)

function apply(next: boolean) {
  derived.value = next

  const placements: Record<string, LabelPosition> = next
    ? labelPlacements(graph)
    : Object.fromEntries(graph.nodes().map(node => [node, 'below' as LabelPosition]))

  for (const [node, placement] of Object.entries(placements)) {
    graph.setNodeAttribute(node, 'labelPlacement', placement)
  }
}

apply(false)
</script>

<template>
  <SigmaGraph :graph="graph" :styles="styles" :settings="{ renderEdgeLabels: false }">
    <SigmaControls>
      <div class="flex gap-1">
        <UButton size="xs" label="一律朝下" :color="derived ? 'neutral' : 'primary'" @click="apply(false)" />
        <UButton size="xs" label="背离邻居" :color="derived ? 'primary' : 'neutral'" @click="apply(true)" />
      </div>
    </SigmaControls>
  </SigmaGraph>
</template>
```

```ts
const placements = labelPlacements(graph)
for (const [node, placement] of Object.entries(placements)) {
  graph.setNodeAttribute(node, 'labelPlacement', placement)
}
```

写进属性后由 styles 的 `labelPosition` 读取。孤立节点没有邻居可参考，一律取 `'below'`。

> [!NOTE]
> 
> 图坐标 y 轴向上、屏幕 y 轴向下，函数内部已经翻转过：邻居在图坐标里的上方，返回的是 
> 
> 'below'
> 
> 。

### 必须在布局之后调用

方位完全由邻居的相对位置决定，坐标一变结论就作废：

```ts
forceAtlas2.assign(graph, { iterations: 200 })
labelPlacements(graph) // 顺序反过来算出来的是初始坐标下的方位
```

### horizontalBias

标签是一条横向的矩形，占的宽度远大于高度，同样是斜角方向，放到左右两侧比放到上下更容易撞上别的东西。因此只有横向分量明显压过纵向时才甩到左右：

```ts
labelPlacements(graph, { horizontalBias: 1 }) // 退化成按象限均分
```

## API

### labelPlacements()

`labelPlacements(graph: Graph, options?: LabelPlacementsOptions): Record<string, LabelPosition>`

#### Parameters

**graph** (`Graph`) *required*: 源 graphology 实例，只读不改。节点须已有 x / y。

**options** (`LabelPlacementsOptions`): 默认 1.6 —— 横向偏置。横向分量超过纵向分量这么多倍时，标签才甩到左右两侧。

#### Returns

`Record<string, LabelPosition>`，节点 key 到 `'above' | 'below' | 'left' | 'right'` 的映射表，可直接写进 styles 的 `labelPosition` 消费的属性。

```ts
import type { LabelPlacementsOptions } from '@movk/sigma'
import type { LabelPosition } from 'sigma/types'
```


## Sitemap

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