---
title: "degreeToTier"
description: "按度数排名给节点分标签档位，返回节点 key 到档位的映射表，档位越小越重要。"
canonical_url: "https://sigma.mhaibaraai.cn/docs/utils/degree-to-tier"
---
# degreeToTier

> 按度数排名给节点分标签档位，返回节点 key 到档位的映射表，档位越小越重要。

## 用法

一张图该出多少标签由屏幕空间决定，与度数的绝对大小无关，所以这里要的是**排名**而非取值：节点尺寸那类连续量用 styles 的数值绑定即可，答的是「这个节点该画多大」；档位把度数压成两三个离散的档，答的是「这个节点的标签该不该出、出多大」。

```vue [DegreeToTierExample.vue]
<script setup lang="ts">
import Graph from 'graphology'
import type { SerializedGraph } from 'graphology-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: {
    labelSize: { attribute: 'labelTier', dict: { 0: 16, 1: 13, 2: 11 }, defaultValue: 12 },
    labelColor: { attribute: 'labelTier', dict: { 0: '#0f172a', 1: '#334155', 2: '#94a3b8' }, defaultValue: '#334155' },
    labelVisibility: { whenData: { labelTier: 0 }, then: 'visible', else: 'auto' }
  }
}

const presets = [
  { label: '15% / 50%', ratios: [0.15, 0.5] },
  { label: '50% / 90%', ratios: [0.5, 0.9] },
  { label: '只分两档', ratios: [0.2] }
]

const current = shallowRef(presets[0]!.label)
const counts = shallowRef<number[]>([])

function apply(preset: typeof presets[number]) {
  current.value = preset.label

  const tiers = degreeToTier(graph, { ratios: preset.ratios })
  const tally = Array.from({ length: preset.ratios.length + 1 }, () => 0)

  for (const [node, tier] of Object.entries(tiers)) {
    graph.setNodeAttribute(node, 'labelTier', tier)
    tally[tier] = (tally[tier] ?? 0) + 1
  }

  counts.value = tally
}

apply(presets[0]!)
</script>

<template>
  <SigmaGraph :graph="graph" :styles="styles" :settings="{ renderEdgeLabels: false }">
    <SigmaControls>
      <div class="flex gap-1">
        <UButton
          v-for="preset in presets"
          :key="preset.label"
          size="xs"
          :label="preset.label"
          :color="current === preset.label ? 'primary' : 'neutral'"
          @click="apply(preset)"
        />
      </div>

      <div class="bg-accented p-2 text-muted text-xs">
        <span v-for="(count, tier) in counts" :key="tier">{{ tier }} 档 {{ count }} 个 </span>
      </div>
    </SigmaControls>
  </SigmaGraph>
</template>
```

```ts
const tiers = degreeToTier(graph)
for (const [node, tier] of Object.entries(tiers)) {
  graph.setNodeAttribute(node, 'labelTier', tier)
}
```

档位有两个去处：交给 styles 的 `dict` 绑定决定字号与配色；用 `labelVisibility: 'visible'` 让枢纽节点不受 sigma 标签网格去重的影响，其余档位留 `'auto'` 参与竞争。再配合 [`useSigmaLabelTiers()`](https://sigma.mhaibaraai.cn/docs/composables/use-sigma-label-tiers)，视野拉远时就能按档位逐级收掉标签。

### ratios 是累计占比

默认 `[0.15, 0.5]` 读作：排名前 15% 是 0 档，前 50% 是 1 档，其余是 2 档。档位数量恒为 `ratios.length + 1`：

```ts
degreeToTier(graph, { ratios: [0.2] })           // 只分两档
degreeToTier(graph, { ratios: [0.1, 0.3, 0.7] }) // 分四档
```

首档向上取整，保证再小的图也至少有一个节点落进最高档；后续各档取四舍五入并保持单调，比例写反或写重也不会让后一档反超前一档。

### rank 只在度数相同时生效

缺省按节点 key 的字典序排定，同一份数据每次结果一致。要引入别的重要度信号：

```ts
degreeToTier(graph, {
  rank: (g, node) => (g.getNodeAttribute(node, 'pagerank') as number) ?? 0
})
```

> [!NOTE]
> 
> 只在
> 
> 度数相同
> 
> 时才比 
> 
> rank
> 
> 。单用 pagerank 排序往往不合适：它已归一化到 0..1 且度数最高的节点恒为 1，服务端新建的节点还可能整个字段都缺。

## API

### degreeToTier()

`degreeToTier(graph: Graph, options?: DegreeToTierOptions): Record<string, number>`

#### Parameters

**graph** (`Graph`) *required*: 源 graphology 实例，只读不改。

**options** (`DegreeToTierOptions`): 默认 [0.15, 0.5] —— 各档位的累计占比，升序。首档向上取整。度数相同时的次级排序依据，返回值越大排名越靠前。缺省按 key 的字典序排定。

#### Returns

`Record<string, number>`，节点 key 到档位的映射表，取值范围 `0` 到 `ratios.length`。空图返回 `{}`。

类型从根出口取：

```ts
import type { DegreeToTierOptions } from '@movk/sigma'
```


## Sitemap

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