# Barcode Detection API（形状检测）

> BarcodeDetector 从图像源中识别平台支持的一维码和二维码。本页说明格式、检测结果、输入错误与手动输入回退。

Barcode Detection API 从图像源中识别一维码和二维码；`BarcodeDetector.detect()` 返回 Promise，各 `DetectedBarcode` 值都包含解码后的 `rawValue`、格式、边界框和角点。

BCD 记录 Android 版 Chrome 83 起完整支持。桌面 Chromium 的支持受平台限制；Safari 17 需开启 Shape Detection API 偏好设置，Firefox 记为不支持（BCD `api.BarcodeDetector`）。

## 语法

```js
new BarcodeDetector()
new BarcodeDetector(options)

BarcodeDetector.getSupportedFormats()
detector.detect(image)
```

此接口仅用于安全上下文，在窗口和 Worker 中暴露；`getSupportedFormats()` 兑现为浏览器理解的格式名，`detect()` 兑现为输入图像中检测到的条码。

## 参数

构造函数接受一个可选成员。

| 成员 | 类型 | 含义 |
|---|---|---|
| `formats` | `string[]` | 把后续检测限制在指定条码格式内。省略时，用户代理应搜索所有受支持格式。 |

`detect(image)` 接受 `HTMLImageElement`、`SVGImageElement`、`HTMLVideoElement`、`HTMLCanvasElement`、`ImageBitmap`、`OffscreenCanvas`、`VideoFrame`、图像 `Blob` 或 `ImageData`。检测结果均含 `boundingBox`、`cornerPoints`、`format` 和 `rawValue` 成员。

## 异常

`formats` 为空或包含 `"unknown"` 时，构造函数抛出 `TypeError`。[`detect()` 算法](https://wicg.github.io/shape-detection-api/#image-sources-for-detection)（WICG）定义了下列失败条件。

| 异常 | 条件 |
|---|---|
| `TypeError` | 没有传入图像，或参数不是接口接受的图像源类型。 |
| `SecurityError` | 图像的有效脚本源不同，或 canvas 并非来源干净。 |
| `InvalidStateError` | `HTMLImageElement` 损坏或尚未完全解码，或视频的 `readyState` 是 `HAVE_NOTHING` 或 `HAVE_METADATA`。 |

:::caution
BCD 记录桌面端为部分支持：Chrome 88 支持 ChromeOS 与 macOS；Edge 83 和 Opera 69 仅列出 macOS。条目还注明，在 macOS Ventura 13 及更高版本上，Chrome 113 以前的接口会静默失败（MDN browser-compat-data 的 [BCD `api.BarcodeDetector`](https://raw.githubusercontent.com/mdn/browser-compat-data/main/api/BarcodeDetector.json)）。
:::

## 示例

创建检测器前先检查构造函数。没有原生条码检测时，用文本框提供手动输入路径。

### 扫描从磁盘选择的图像

下面的代码创建图像选择器、手动输入框和输出元素。支持此 API 的浏览器扫描所选图像 `Blob`，其他浏览器保留手动输入。

```js
const picker = document.body.appendChild(document.createElement("input"));
const manual = document.body.appendChild(document.createElement("input"));
const output = document.body.appendChild(document.createElement("p"));
picker.type = "file";
picker.accept = "image/*";
manual.placeholder = "手动输入条码内容";

if (!("BarcodeDetector" in globalThis)) {
  picker.disabled = true;
  output.textContent = "无法自动扫描，请手动输入。";
} else {
  const detector = new BarcodeDetector();
  picker.addEventListener("change", async () => {
    const [file] = picker.files;
    if (!file) return;
    const codes = await detector.detect(file);
    output.textContent = codes[0]?.rawValue ?? "未检测到条码";
  });
}
```

即使检测器存在，手动输入框仍留在文档中；检测结果为空时，用户仍可继续输入。

### 只请求平台支持的格式

创建二维码检测器前，先读取浏览器的格式列表。接口或格式不可用时返回 `null`。

```js
async function createQrDetector() {
  if (!("BarcodeDetector" in globalThis)) return null;

  const formats = await BarcodeDetector.getSupportedFormats();
  if (!formats.includes("qr_code")) return null;
  return new BarcodeDetector({ formats: ["qr_code"] });
}

const detector = await createQrDetector();
if (!detector) console.info("请使用手动输入框");
```

函数返回 `null` 时，调用方可以继续保留手动输入。

## 另请参阅

- [Screen Capture API](/zh/reference/capabilities/screen-capture/)，用于从屏幕捕获中取得画面
- [Generic Sensor API](/zh/reference/capabilities/sensors/)，另一个限安全上下文使用的设备 API
- [Accelerated Shape Detection in Images](https://wicg.github.io/shape-detection-api/#barcode-detection-api)（wicg.github.io）
- [Barcode Detection API](https://developer.mozilla.org/en-US/docs/Web/API/Barcode_Detection_API)（MDN）