> **本文回答**：Symbol 的文字 (`text-*`) —— textField / textFont / halo / 排布 / 旋转。

## 一、最简

```js
new vjmap.Symbol({
  data: map.toLngLat(features),
  textField: ["get", "name"],
  textSize: 12,
  textColor: "#000",
  textHaloColor: "#fff",
  textHaloWidth: 1
}).addTo(map);
```

## 二、参数表（文字）

| 参数 | 默认 | 说明 |
|---|---|---|
| `textField` | — | 文字内容（可表达式） |
| `textFont` | `["Open Sans Regular", "Arial Unicode MS Regular"]` | 字体栈（整个数组逗号拼接成一个 fontstack 请求 PBF，不是前端逐个回退）；官方示例用 `["Arial Unicode MS Regular"]` |
| `textSize` | 16 | 字号 |
| `textMaxWidth` | 10 em | 最大行宽 |
| `textLineHeight` | 1.2 | 行高 |
| `textLetterSpacing` | 0 | 字间距 |
| `textAnchor` | "center" | 9 向锚点 |
| `textOffset` | `[0,0]` | 字号单位偏移（em） |
| `textRotate` | 0 | 旋转角度 |
| `textJustify` | "center" | auto/left/center/right |
| `textPadding` | 2 | 碰撞时的像素间距 |
| `textAllowOverlap` | false | 允许重叠 |
| `textIgnorePlacement` | false | 忽略位置冲突 |
| `textOptional` | false | 配 icon 时：**文字**被碰撞剔除而图标未碰撞时，图标是否仍单独显示（反过来"图标被剔、文字单独显示"是 `iconOptional`） |
| `textTransform` | "none" | none/uppercase/lowercase |
| `textWritingMode` | 无默认 | 数组，元素取 horizontal / vertical（按顺序尝试的书写方向，只对点状排布生效） |
| `textMaxAngle` | 45 | 沿线方向的最大弯折角 |
| `textKeepUpright` | true | 旋转时保持文字正立 |
| `textRotationAlignment` | "auto" | map/viewport |
| `textPitchAlignment` | "auto" | map/viewport |
| `textColor` | "#000" | 填充色 |
| `textOpacity` | 1 | 透明度 |
| `textHaloColor` | `rgba(0,0,0,0)` | 描边色 |
| `textHaloWidth` | 0 | 描边宽 |
| `textHaloBlur` | 0 | 描边模糊 |

## 三、textField 的三种写法

### 3.1 字面量

```js
textField: "固定文字"
```

### 3.2 取属性

```js
textField: ["get", "name"]
```

### 3.3 格式化（多行 / 粗体）

```js
textField: [
  "format",
  ["get", "name"], { "font-scale": 1.2 },
  "\n", {},
  ["get", "description"], { "font-scale": 0.8, "text-color": "#888" }
]
```

## 四、字体

```js
textFont: ["Arial Unicode MS Regular"]   // 官方示例用的 fontstack
```

中文等 CJK 字符默认由浏览器本地字体（Map 选项 `localIdeographFontFamily`，默认 `'sans-serif'`）绘制，不走 glyphs，`textFont` 对它们只影响字重。

vjmap 后端默认提供 `simsun` / `Arial Unicode MS Regular` 等字体。自定义字体需部署 glyphs PBF（见 [sprite-glyphs](../map-style/sprite-glyphs.md)）。

## 五、文字沿线排布

```js
new vjmap.Symbol({
  data: lineFeatures,
  symbolPlacement: "line",          // 沿线
  symbolSpacing: 200,               // 重复间距（像素）
  textField: ["get", "name"],
  textSize: 12,
  textRotationAlignment: "map"
}).addTo(map);
```

`symbolPlacement`：`point` / `line` / `line-center`。

## 六、halo 描边

```js
textColor: "#000",
textHaloColor: "#fff",
textHaloWidth: 1.5,
textHaloBlur: 0.5
```

典型：深色底图上白描边，浅色底图上黑描边。

## 七、数据驱动

```js
textSize: ["interpolate", ["linear"], ["zoom"], 10, 10, 16, 18],
textColor: ["match", ["get", "level"], "high", "#f00", "low", "#888", "#333"],
textField: ["concat", ["get", "name"], " (", ["to-string", ["get", "count"]], ")"]
```

## 八、自动多向锚点（避让）

```js
textVariableAnchor: ["top", "bottom", "left", "right"],
textRadialOffset: 0.8,
textJustify: "auto"
```

渲染引擎会根据碰撞自动选择一个方向。

## 九、常见坑

1. **textField 属性值不是字符串** → 用 `["to-string", ["get", "x"]]` 转换。
2. **中文 / 文字不显示** → 与 textFont 是否"支持中文"无关（CJK 默认本地绘制）。多半是：style 缺 `glyphs`（带文字的图层校验失败）、字体栈 PBF 404（整瓦片解析失败）、或 textField 取值为空。
3. **文字叠压消失** → 碰撞生效；`textAllowOverlap: true` 或 `textIgnorePlacement: true`。
4. **halo 比文字大**：`textHaloWidth` 最多渲染到 1/4 字号。
5. **沿线文字翻转** → `textKeepUpright: true`。
