npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tiger-vue3-hand-gesture-camera

v1.0.4

Published

Vue 3 hand gesture camera component powered by MediaPipe.

Downloads

683

Readme

tiger-vue3-hand-gesture-camera 使用说明书

tiger-vue3-hand-gesture-camera 是一个基于 Vue 3 的手势识别组件插件,集成了:

  • MediaPipe 手势识别(双手)
  • 可选二维码识别(浏览器支持 BarcodeDetector 时启用)
  • 可选人脸识别:定时截取视频帧,以 Base64 调用业务后端 /recognize,顶部居中展示员工号
  • 可选粒子视觉效果(PIXI + GSAP)

适用于希望在 Vue3 项目中快速接入摄像头手势交互的场景。


1. 安装

npm i tiger-vue3-hand-gesture-camera

1.1 样式(重要)

原因说明:早期版本(如 1.0.0)在 Vite 库模式下会把样式打到单独的 dist/*.css 里,而入口 JS 没有自动 import 这份 CSS。你在业务项目里只写了 import ... from 'tiger-vue3-hand-gesture-camera' 时,功能 JS 有、样式 CSS 没进打包链,看起来就像「样式完全失效」。

1.0.1:ESM 产物会在入口自动带上 import './index.css',一般无需再手动引样式。

若你的构建工具仍不处理该 CSS(极少数场景),可在应用入口手动补一行:

import 'tiger-vue3-hand-gesture-camera/style.css'

1.2 作为页面中的一块区域(布局)

  • 组件内部摄像头区域使用 position: absolute 铺满根容器 .hgc-root
  • 请保证外层有高度,或使用组件属性 min-height(对应 prop:minHeight,默认 280px)。

示例:

<div style="height: 420px">
  <HandGestureCamera min-height="100%" />
</div>

2. 快速开始

2.1 全局注册(推荐)

import { createApp } from 'vue'
import App from './App.vue'
import HandGesturePlugin from 'tiger-vue3-hand-gesture-camera'

createApp(App).use(HandGesturePlugin).mount('#app')

在任意页面中直接使用:

<template>
  <HandGestureCamera
    @gesture="onGesture"
    @gesture-confirmed="onGestureConfirmed"
    @qr-detected="onQr"
    @face-recognized="onFaceRecognized"
    @face-confirmed="onFaceConfirmed"
    @face-error="onFaceError"
    @error="onError"
  />
</template>

<script setup>
function onGesture(payload) {
  console.log('gesture:', payload)
}

function onQr(text) {
  console.log('qr:', text)
}

function onFaceRecognized(employeeNo) {
  console.log('员工号(变化即触发):', employeeNo)
}

function onGestureConfirmed(payload) {
  console.log('手势(防抖确认):', payload)
}

function onFaceConfirmed(employeeNo) {
  console.log('员工号(防抖确认):', employeeNo)
}

function onFaceError(err) {
  console.warn('人脸识别请求失败:', err)
}

function onError(err) {
  console.error(err)
}
</script>

2.2 局部按需引入

import { HandGestureCamera } from 'tiger-vue3-hand-gesture-camera'

3. 完整示例(推荐配置)

<template>
  <HandGestureCamera
    :mediapipe-wasm-base="'https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/wasm'"
    :mediapipe-model-path="'https://storage.googleapis.com/mediapipe-models/gesture_recognizer/gesture_recognizer/float16/1/gesture_recognizer.task'"
    :gesture-confirm-ms="1000"
    :qr-scan-interval-ms="120"
    :qr-label-ttl-ms="3000"
    :enable-qr="true"
    :video-constraints="{ video: { facingMode: 'user' }, audio: false }"
    :displacement-map-url="'/images/displacement_map_repeat.jpg'"
    face-api-base-url="https://your-api.example.com"
    :face-recognize-interval-ms="1800"
    :face-stable-count="2"
    :gesture-emit-debounce-ms="400"
    :face-emit-debounce-ms="500"
    @gesture="onGesture"
    @gesture-confirmed="onGestureConfirmed"
    @qr-detected="onQrDetected"
    @face-recognized="onFaceRecognized"
    @face-confirmed="onFaceConfirmed"
    @face-error="onFaceError"
    @error="onError"
  />
</template>

<script setup>
function onGesture(payload) {
  // payload: { left, right, label }
  console.log(payload)
}

function onQrDetected(text) {
  console.log('二维码内容:', text)
}

function onFaceRecognized(employeeNo) {
  console.log('人脸识别员工号(变化即触发):', employeeNo)
}

function onGestureConfirmed(payload) {
  console.log('手势防抖确认:', payload)
}

function onFaceConfirmed(employeeNo) {
  console.log('员工号防抖确认:', employeeNo)
}

function onFaceError(err) {
  console.warn('人脸识别失败:', err)
}

function onError(err) {
  console.error('插件运行错误:', err)
}
</script>

4. Props 参数说明

| 参数名 | 类型 | 默认值 | 说明 | | --- | --- | --- | --- | | mediapipeWasmBase | string | https://cdn.jsdelivr.net/npm/@mediapipe/[email protected]/wasm | MediaPipe wasm 资源路径 | | mediapipeModelPath | string | https://storage.googleapis.com/mediapipe-models/gesture_recognizer/gesture_recognizer/float16/1/gesture_recognizer.task | 手势模型文件地址 | | gestureConfirmMs | number | 1000 | 手势稳定判定时长(毫秒) | | qrScanIntervalMs | number | 120 | 二维码识别节流间隔(毫秒) | | qrLabelTtlMs | number | 3000 | 二维码文字显示保留时长(毫秒) | | enableQr | boolean | true | 是否启用二维码识别 | | videoConstraints | MediaStreamConstraints | { video: true } | 摄像头采集参数 | | displacementMapUrl | string | '' | 视觉特效贴图 URL,留空则关闭位移滤镜 | | minHeight | string | '280px' | 根容器最小高度,嵌入页面时避免高度为 0 | | faceApiBaseUrl | string | '' | 人脸识别服务基础地址(不含路径末尾斜杠)。设置后组件会请求 {faceApiBaseUrl}/recognize;留空则不请求人脸识别 | | faceRecognizeIntervalMs | number | 1800 | 人脸识别请求节流间隔(毫秒),避免每帧打接口 | | faceStableCount | number | 2 | 连续若干次识别到同一员工号后,才更新顶部展示并触发 face-recognized,用于现场抗抖 | | gestureEmitDebounceMs | number | 400 | 手势签名(左右手 key + 中文标签)连续不变达到该时长后,触发一次 gesture-confirmed(尾随防抖) | | faceEmitDebounceMs | number | 500 | 在触发 face-recognized(工号变化)后,再经过该静默时长且界面工号未变,触发一次 face-confirmed(尾随防抖;工号快速切换会重置计时) |

4.1 人脸识别后端约定

  • 请求POST {faceApiBaseUrl}/recognize
  • 请求头Content-Type: application/json
  • 请求体{ "image": "<JPEG 的纯 Base64,不含 data:image 前缀>" }
  • 响应:JSON。组件会从返回体中递归查找常见工号字段(如 employeeNoemployee_idjobNocode 等),取到非空字符串即视为识别成功。
  • 界面:识别稳定后,页面顶部居中显示「员工号:xxx」。
  • 跨域:浏览器直接请求后端时,后端需配置 CORS;若无法改后端,可在业务侧用同源代理转发到真实识别服务。

5. 事件说明

5.1 gesture

手势在 MediaPipe 稳定判定(gestureConfirmMs)后,仅在签名变化时触发(left / right / label 与上一帧不同才派发),避免原先每帧重复触发。

type GesturePayload = {
  left: string   // 左手手势 key
  right: string  // 右手手势 key
  label: string  // 中文标签(例如:左手OK(确定),右手竖拇指)
}

无手势时 label 可能为空字符串;从「有手势」变为「无手势」时也会派发一次变化后的载荷,便于父组件清空状态。

5.2 gesture-confirmed

gesture 所用同一套稳定手势数据上再做尾随防抖:手势签名连续不变达到 gestureEmitDebounceMs 后,仅派发一次,载荷类型同 GesturePayload。适合业务侧写库、开门等「只要最终确定结果」的场景。

5.3 qr-detected

识别到二维码文本后触发。

  • 回调参数:string(二维码内容)

5.4 face-recognized

人脸识别稳定通过、且解析到员工号后触发(同一员工号仅在变化时再次触发,避免刷屏)。

  • 回调参数:string(员工号)

5.5 face-confirmed

face-recognized 触发(工号相对上一次展示发生变化)后,再经过 faceEmitDebounceMs 且界面当前工号仍与本次一致时派发一次,用于父组件落库等,减轻短抖动。若在该时长内工号再次变化,会重新计时。

  • 回调参数:string(员工号)

5.6 face-error

人脸识别流程异常时触发(网络失败、HTTP 非 2xx、response.json() 解析失败等)。不会走全局 error 事件,避免与手势/摄像头错误混在一起刷屏。

  • 回调参数:Error | unknown

5.7 error

运行异常时触发(如摄像头权限、MediaPipe 模型加载失败等)。不包含人脸识别接口失败(见 face-error)。

  • 回调参数:Error | unknown

6. 手势说明(当前实现)

  • 内置 MediaPipe 预置手势(如:Thumb_UpVictory 等)
  • 额外支持通过关键点判断 OK 手势(LANDMARK_OK
  • 组件会做稳定判定,避免每帧抖动导致频繁变化

7. 在业务里推荐的接入方式

  • 在页面首次进入时请求摄像头权限,并给出明显提示
  • 需要低频、确定结果时,优先监听 @gesture-confirmed@face-confirmed@gesture 仅在签名变化时触发,适合 HUD 或轻量联动
  • @error 统一接入你的错误上报系统(手势与摄像头相关)
  • @face-error 单独处理或降级提示(识别服务不稳定时不宜当作致命错误)
  • @face-recognized 绑定门禁、签到等业务;faceApiBaseUrl 由环境或父项目配置注入,便于多项目复用同一组件
  • 生产环境建议固定 mediapipeModelPath 到你可控的静态资源地址

8. 常见问题(FAQ)

8.1 摄像头打不开

  • 检查浏览器权限是否允许摄像头
  • 页面建议在 httpslocalhost 下运行
  • 查看 @error 回调日志定位具体问题

8.2 二维码识别不工作

  • 浏览器需支持 BarcodeDetector
  • enableQr 需要为 true
  • 可通过控制台查看是否有识别输出

8.3 识别延迟或卡顿

  • 提高 gestureConfirmMs 会更稳但更慢
  • 适当增大 qrScanIntervalMs 降低二维码识别频率
  • 适当增大 faceRecognizeIntervalMs 降低人脸识别接口频率
  • 减少页面其他高负载动画/渲染任务

8.4 人脸识别无反应或收不到 face-recognized

  • 确认已设置 face-api-base-url(或 faceApiBaseUrl),且实际请求地址为 {base}/recognize
  • 打开开发者工具 Network,查看请求是否发出、状态码与响应体结构;若字段名不在组件内置列表中,需调整后端返回上述常见键名之一,或扩展组件内解析逻辑
  • 若连续识别结果不一致,可提高 face-stable-count 再试
  • 跨域被拦截时,控制台会出现 CORS 相关错误,请配置后端 CORS 或走前端代理

9. TypeScript 支持

包内已包含类型声明文件,可直接在 TS 项目中使用:

import HandGesturePlugin, { HandGestureCamera } from 'tiger-vue3-hand-gesture-camera'

10. 本地构建(维护者)

npm run build:lib

11. 发布到 npm(维护者)

11.1 首次发布前

npm login
npm view tiger-vue3-hand-gesture-camera

11.2 发布

npm publish --access public

如果账号开启了 2FA,请带 OTP:

npm publish --access public --otp=123456

11.3 版本升级发布

npm version patch
npm publish --access public

11.4 使用 npm token 发布(维护者)

勿将 token 写入仓库或 README。在本地使用环境变量或 npm login 完成鉴权后执行 npm publish 即可。