antvis / antvis/Infographic

文本间距属性 (letter/wordSpacing) 在测量层缺失且在业务组件层未透传,导致排版功能不可用

Open
#184 1 comment 2 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
6.6k
Forks
543
Avg merge
11h 33m
Merged PRs (30d)
3

Description

## 问题描述

官方文档声明 `Text `原语([原语节点](https://infographic.antv.vision/reference/primitive-nodes#text))支持 letterSpacing 和 wordSpacing。但是该功能似乎不可用,问题贯穿了从底层的 测量算法 到中间的 样式解析 再到上层的 业务组件封装 的完整链路。

## 代码分析

### **1. 底层:测量函数忽略(measureText)**

- **`measureText` 实现忽略:** 在 `src/utils/measure-text.ts` 中,逻辑只解构了 `fontFamily`, `fontSize`, `fontWeight`, `lineHeight`,完全忽略了 `letterSpacing` 和 `wordSpacing`。
- **调用链路截断:** `src/utils/text.ts` 中的 `updateTextElement` 在调用 `measureText` 时,显式解构并过滤了样式属性,直接丢弃了这两个属性。

### **2.中间层: 样式解析不一致**

- **渲染属性白名单缺失**:在 `src/renderer/composites/text.ts` 的 `getTextAttributes` 函数中,使用了白名单机制提取 SVG 属性。
- **现状:** 该白名单包含 `'letter-spacing'`,但**漏掉了 `'word-spacing'`**。
- **后果:** 即使上层传入了 `wordSpacing`,它也会在最终生成 SVG `foreignObject` 内容时被剥离,无法渲染出视觉效果。

- 在`src/utils/text.ts`中的`getTextStyle`函数对`letterSpacing`做了处理,加上了`px`,但是没有对`wordSpacing`做处理。

### 3.**顶层:业务组件透传阻断**

​ 虽然原子组件 `ItemLabel`/`ItemValue` /`ItemDes`支持透传 `TextProps`,但在 `SimpleItem`、`BadgeCard` 等业务组件中,**并没有开放接口**来配置内部文本的间距,也没有将`letterSpacing`和`wordSpacing`透传给文本节点。

### 4.总结:文本属性支持情况对比表

| **层级** | **问题** | **letterSpacing** | **wordSpacing** |
| ----------------------------------- | ---------------- | ----------------- | --------------- |
| **底层** (`measureText`) | 测量忽略间距属性 | ❌ 不支持 | ❌ 不支持 |
| **中间层** (`text.ts getTextStyle`) | px 后缀处理 | ✅ 有处理 | ❌ 无处理 |
| **中间层** (`composites/text.ts`) | 渲染白名单 | ✅ 已包含 | ❌ 缺失 |
| **原语层** (`jsx Text`) | 属性透传 | ✅ 正确 | ✅ 正确 |
| **业务组件层** | 接口暴露 | ❌ 未暴露 | ❌ 未暴露 |
## 建议方案

**Step 1: 修复核心渲染与测量 (Core Fix)**

- [ ] **Refactor `measureText`**: 升级函数签名,支持传入 `letterSpacing` 和 `wordSpacing`。
- [ ] **Fix `utils/text.ts`**: 在 `updateTextElement` 中正确透传这两个属性给测量函数。并且在`getTextStyle`函数中添加对`wordSpacing`的处理。
- [ ] **Fix `renderer/composites/text.ts`**: 在 `getTextAttributes` 的白名单数组中添加 `'word-spacing'`。

**Step 2: 修复组件层数据流 (Component Fix)**

- [ ] **Update Business Components**: 修改 `SimpleItem` 等组件,允许通过 props (如 `labelStyle`) 传入间距属性,并将其透传给内部的 `ItemLabel` / `ItemDesc`。

**Step 3:性能优化 (Performance Optimization - 可选)**

- [ ] **实现 LRU 缓存:** 我发现 `measureText` 在每次调用时都会触发 Canvas/DOM 测量,而没有任何缓存机制。我建议引入 **LRU (Least Recently Used)** 缓存机制(例如通过项目现有的 `flru` 库实现)。

> **备注:** 我已经准备好了一套本地实现LRU的方案。

**如果维护者同意,我愿意参与第一步(核心修复)和第三步(性能优化)。**

Contributor guide

No contributing guide indexed for this repository

Research direction

Read src/utils/measure-text.ts and src/utils/text.ts first, then trace the text attribute whitelist in src/renderer/composites/text.ts and the SimpleItem/BadgeCard component props. Confirm how spacing is measured, styled, rendered, and passed through; done means the named paths consistently support both spacing properties, with component behavior verified where applicable.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
frontend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.