# 标尺显隐集成指南

本文档面向**接入众趣 zqsdk 的开发者**，说明如何在自己的项目中实现「全景标尺」的显隐控制与展示。标尺用于在全景模式下测量并显示空间中左/右/高三个方向的尺寸（如「约 3.5m」），由 SDK 在开启监听后通过事件下发数据，UI 完全由你自定义绘制。

---

## 一、功能简介与前置条件

### 1.1 什么是全景标尺

全景标尺是在**全景模式（panorama）**下，由 SDK 计算并派发的**三条测量线**数据：

- **left**：左侧某段距离的标尺；
- **right**：右侧某段距离的标尺；
- **height**：高度方向某段距离的标尺。

每条标尺包含：在画布上的**起点坐标**、**线段长度（像素）**、**旋转角度**以及**格式化后的尺寸文案**（如「约 3.5m」）。你需要在开启标尺后监听 SDK 事件，根据数据在画布上绘制线段与文案，并提供一个「标尺开关」控制显隐。

### 1.2 展示效果

![全景标尺展示效果](../../screenshot/ruler/全景标尺.png)


### 1.3 前置条件

- 已接入众趣 zqsdk，在 `complete` 回调中拿到 `housePlay` 并已调用 `housePlay.start()`。
- 标尺为**可选功能**：仅当用户点击「开启标尺」后才调用 SDK 的开启方法，此后 SDK 才会派发 `updatePanoSize` 事件；关闭后调用关闭方法，事件停止派发。

---

## 二、集成步骤概览

| 步骤 | 内容 |
|------|------|
| 1 | 提供「标尺」开关（如底部工具栏按钮），用户点击时根据开关状态调用 SDK 的开启/关闭方法 |
| 2 | 在 housePlay 上注册 `updatePanoSize` 事件，将三条线（left/right/height）的显隐与数据同步到你的状态 |
| 3 | 根据状态在画布上绘制三条标尺线（位置、长度、角度、文案），单位换算可依赖 `window.conf` |

以下按步骤展开。

---

## 三、第一步：控制标尺的开启与关闭

**SDK 方法**（均在 `housePlay` 上调用）：

| 方法 | 说明 |
|------|------|
| `housePlay.enablePanoramaSize()` 或 `housePlay.enablePanramaSize()` | 开启标尺功能；此后 SDK 会派发 `updatePanoSize` 事件 |
| `housePlay.disablePanoramaSize()` | 关闭标尺功能；事件停止派发 |

注意：部分 SDK 拼写为 `enablePanramaSize`（少一个 o），建议兼容两种写法。

```javascript
function setRulerVisible(visible) {
  const hp = window.housePlay
  if (!hp) return

  if (visible) {
    hp.enablePanoramaSize ? hp.enablePanoramaSize() : (hp.enablePanramaSize && hp.enablePanramaSize())
  } else {
    hp.disablePanoramaSize && hp.disablePanoramaSize()
  }
}
```

**建议**：在你自己项目中维护一个「标尺是否开启」的状态，与底部栏或设置中的「标尺」开关绑定；用户打开开关时设为 true 并调用上述开启方法，关闭时设为 false 并调用关闭方法。该状态仅表示「用户意图」，实际是否显示某条线由 `updatePanoSize` 的 `isShow` 决定。

---

## 四、第二步：注册 updatePanoSize 并更新状态

**事件**：`housePlay.on('updatePanoSize', function(style, isShow, data) { ... })`

- **style**：字符串，取值为 `'left'`、`'right'`、`'height'` 之一，表示当前更新的是哪条标尺。
- **isShow**：布尔值，该条标尺是否显示（true 显示，false 隐藏）。
- **data**：该条标尺的原始数据，通常包含：
  - `point`：起点坐标，可能为 `{ x, y }` 或 `{ left, top }`，像素值；
  - `dis`：线段长度（像素）；
  - `angle`：旋转角度（度）；
  - `length`：原始长度，可能为数值（米）或已格式化的字符串；若为数值，需用 `conf.unit_conversion_value` 与 `conf.unit_name` 换算为展示文案（如「3.5m」）。

**只有执行开启方法后**，SDK 才会派发 `updatePanoSize`；关闭后不再派发，你之前保存的三条线数据可保留，但可根据「标尺开关」整体隐藏绘制。

```javascript
const state = {
  left:  { isShow: false, point: { x: 0, y: 0 }, dis: 0, angle: 0, length: '' },
  right: { isShow: false, point: { x: 0, y: 0 }, dis: 0, angle: 0, length: '' },
  height: { isShow: false, point: { x: 0, y: 0 }, dis: 0, angle: 0, length: '' }
}

housePlay.on('updatePanoSize', function(style, isShow, data) {
  const conf = window.conf || {}
  const unitConversion = conf.unit_conversion_value != null ? conf.unit_conversion_value : 1
  const unitName = conf.unit_name || 'm'

  const rawLen = data.length
  const lengthText = typeof rawLen === 'number'
    ? (rawLen * unitConversion).toFixed(1) + unitName
    : String(rawLen || '')

  const px = data.point ? (data.point.x != null ? data.point.x : data.point.left) : 0
  const py = data.point ? (data.point.y != null ? data.point.y : data.point.top) : 0
  if (px == null) px = 0
  if (py == null) py = 0

  const item = {
    isShow: isShow,
    point: { x: px, y: py },
    dis: data.dis,
    angle: data.angle,
    length: lengthText
  }

  if (style === 'left') state.left = item
  else if (style === 'right') state.right = item
  else if (style === 'height') state.height = item

  yourApp.updateRulerState(state)
})
```

上面 `point` 的写法可简化为：`x: data.point?.x ?? data.point?.left ?? 0`，`y: data.point?.y ?? data.point?.top ?? 0`（视运行环境支持可选链与否）。

---

## 五、第三步：根据状态绘制标尺 UI

你需要在**全景画布上层**（或与 3D 同层的覆盖层）根据三条线的 `isShow`、`point`、`dis`、`angle`、`length` 绘制：

- 线段：从 `point` 出发，按 `angle` 旋转，长度为 `dis` 像素；
- 文案：在合适位置（如线段中点或端点）显示 `length`（如「约 3.5m」），建议加「约」前缀以与 SDK 文档一致。

样式（颜色、线宽、字体等）完全由你自定义；可参考众趣 demo 的渐变线段 + 端点标记 + 文案。绘制时注意与 3D 容器的 z-index 关系，确保标尺在场景之上、在其他 HUD 之下或按设计排列。

---

## 六、API 速查表

### 6.1 方法（housePlay）

| 方法 | 说明 |
|------|------|
| `enablePanoramaSize()` 或 `enablePanramaSize()` | 开启标尺；之后会派发 `updatePanoSize` |
| `disablePanoramaSize()` | 关闭标尺；停止派发 |

### 6.2 事件（housePlay.on）

| 事件 | 回调参数 | 说明 |
|------|----------|------|
| `updatePanoSize` | `(style, isShow, data)` | style: `'left'` \| `'right'` \| `'height'`；isShow: 是否显示该条；data: point/dis/angle/length |

### 6.3 配置（window.conf）

- `unit_conversion_value`：长度数值换算系数（默认 1）；
- `unit_name`：单位名称（如 `'m'`），用于拼接文案。

---

## 七、常见问题与注意事项

1. **先开启再收事件**：只有调用了 `enablePanoramaSize`（或 `enablePanramaSize`）后，`updatePanoSize` 才会触发；关闭后不再触发，你可根据「标尺开关」决定是否绘制已缓存的三条线。
2. **point 字段**：不同版本可能用 `x/y` 或 `left/top`，建议做兼容读取。
3. **length 类型**：可能是 number（米）或 string，做单位换算时先判断类型再格式化为「约 X.Xm」等形式。

---

以上完成即可在自己的项目中实现标尺的显隐控制与展示。本仓库实现可参考 `src/stores/vr.ts` 中的 `setRulerVisible` 与 `updatePanoSize` 处理，以及 `src/modules/pc/NestPanoSize.vue` 的绘制逻辑。
