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

@vue-puzzle-vcode/ui

v2.0.2

Published

vue 滑动拼图验证码 — sliding puzzle captcha components for Vue 2.7 & Vue 3

Readme

vue-puzzle-vcode npm npm downloads

Vue 纯前端的拼图人机验证、右滑拼图验证。不依赖任何第三方 SDK 与后端接口,纯 Canvas 本地生成校验。

同时支持 Vue 2.7 与 Vue 3(基于 vue-demi,vue 为 peer dependency,不会向你的项目引入第二个 Vue)。

Demo:Vue 3 · Vue 2.7

img

项目来源

本项目继承自 javaLuo/vue-puzzle-vcode,感谢原作者 javaLuo(L) 的开源工作。本仓库是在原项目基础上的升级重构:webpack → Vite、单组件 → Radix 风格组合式部件、仅 Vue 2.6 → 同时支持 Vue 2.7 与 Vue 3、vue 移出生产依赖改为 peer dependency。验证交互与 Canvas 绘制逻辑沿袭原作。

特性

  • 🔀 一套代码同时跑在 Vue 2.7 与 Vue 3 上
  • 🧩 Radix 风格的组合式部件:VcodeRoot 提供上下文,VcodeOverlay / VcodeSlider 等部件通过 inject 接入,每一层都可替换、可自定义 slot
  • 🎛 Headless 状态机 useVcode:逻辑与视图完全解耦,可完全自建 UI
  • 🖼 无图模式下用 Canvas 随机生成背景图,也可以传入自己的图片数组
  • 📦 vue 仅作为 peer dependency,杜绝双 Vue 问题

安装

pnpm add @vue-puzzle-vcode/ui
# npm i @vue-puzzle-vcode/ui / yarn add @vue-puzzle-vcode/ui

项目需已安装 vue@^2.7 || ^3(peer dependency)。vue-demi 会在安装时自动切换到与你项目匹配的版本。

快速开始(默认组件)

Vue 3

<script setup>
import { ref } from 'vue'
import Vcode from '@vue-puzzle-vcode/ui'
import '@vue-puzzle-vcode/ui/style.css'

const show = ref(false)
</script>

<template>
  <button @click="show = true">验证</button>
  <Vcode
    v-model:show="show"
    :imgs="['https://picsum.photos/seed/a/310/160']"
    @success="(diff) => console.log('通过', diff)"
    @fail="(diff) => console.log('失败', diff)"
  />
</template>

Vue 2.7

模板写法的唯一区别:用 .sync 代替 v-model:show

<script>
import Vcode from '@vue-puzzle-vcode/ui'
import '@vue-puzzle-vcode/ui/style.css'

export default {
  components: { Vcode },
  data: () => ({ show: false }),
}
</script>

<template>
  <Vcode :show.sync="show" @success="onSuccess" @fail="onFail" />
</template>

也可以 app.use(VcodePlugin)(Vue 2.7 用 Vue.use(VcodePlugin))全局注册全部部件。

Props

| Prop | 类型 | 默认值 | 说明 | | ------------- | ---------- | -------------------- | ------------------------------------- | | show | boolean | false | 显隐,受控;配合 v-model:show / .sync | | canvasWidth | number | 310 | 主画布宽 | | canvasHeight| number | 160 | 主画布高 | | puzzleScale | number | 1 | 拼图块缩放,钳制在 0.2 ~ 2 | | sliderSize | number | 50 | 滑块尺寸 | | range | number | 10 | 判定成功的允许像素误差 | | imgs | string[] | undefined | 自定义背景图;缺省时 Canvas 随机生成 | | successText | string | 验证通过! | 成功提示文案 | | failText | string | 验证失败,请重试 | 失败提示文案 | | sliderText | string | 拖动滑块完成拼图 | 滑轨文案 |

Events

| 事件 | 参数 | 说明 | | ------------- | --------------- | -------------------------------------- | | update:show | show: boolean | 组件请求关闭时触发(目前仅点遮罩关闭);需父级同步改 show | | success | diff: number | 验证通过,diff 为像素偏差;不会自动关闭,请在回调里自行 show = false | | fail | diff: number | 验证失败(800ms 后自动重置拼图) | | close | — | 请求关闭(与 update:show(false) 同步触发) |

默认组件的 Slots

<Vcode> 内部就是一套默认组合,以下插槽可逐块替换:

| Slot | 作用域参数 | 说明 | | ------------- | --------------------- | -------------------- | | loading | — | 加载动画区域 | | message | { text, fail } | 顶部提示条 | | refresh | — | 右上角刷新按钮内容 | | thumb | — | 滑块手柄内容 | | slider-text | — | 滑轨文字 |

组合式部件(Radix 风格)

想要完全自定义某一层?用部件自行组合。VcodeRoot 创建状态机并 provide 上下文,其余部件通过 inject 接入,任意一层都可以换成你自己的实现:

<script setup>
import {
  VcodeRoot, VcodePortal, VcodeOverlay, VcodePanel, VcodeBoard,
  VcodeCanvasMain, VcodeCanvasPuzzle, VcodeCanvasSuccess,
  VcodeFlash, VcodeLoading, VcodeMessage, VcodeRefresh,
  VcodeSlider, VcodeSliderProgress, VcodeSliderThumb,
} from '@vue-puzzle-vcode/ui'
</script>

<template>
  <VcodeRoot v-model:show="show" @success="ok" @fail="bad">
    <VcodePortal>
      <!-- 遮罩:随便加自己的 class / 过渡;Panel 必须是 Overlay 的子节点 -->
      <VcodeOverlay class="bg-slate-900/60 backdrop-blur-sm">
        <VcodePanel>
          <VcodeBoard>
            <VcodeCanvasMain />
            <VcodeCanvasSuccess />
            <VcodeCanvasPuzzle />
            <VcodeLoading />
            <VcodeFlash />
            <VcodeRefresh>
              <button class="my-refresh">↻</button>
            </VcodeRefresh>
            <VcodeMessage v-slot="{ text, fail }">
              <div :class="fail ? 'msg msg--fail' : 'msg'">{{ text }}</div>
            </VcodeMessage>
          </VcodeBoard>
          <VcodeSlider>
            <VcodeSliderProgress>
              <VcodeSliderThumb><span>⇥</span></VcodeSliderThumb>
            </VcodeSliderProgress>
          </VcodeSlider>
        </VcodePanel>
      </VcodeOverlay>
    </VcodePortal>
  </VcodeRoot>
</template>

默认导出 <Vcode> 就是以上部件的一套官方组合,二者 API(props / events)完全一致。

部件说明

默认组合的嵌套结构(缩进 = 父子关系):

Vcode                    默认整体组件 = 下面这棵树的官方封装
└─ VcodeRoot             [必需] 无渲染根:创建状态机、provide 上下文、
   │                     绑定 document 级拖拽监听、show 时锁 body 滚动
   └─ VcodePortal        把子树挂到 document.body(Vue2 安全的 Teleport)
      └─ VcodeOverlay    全屏遮罩;按下并抬起都在遮罩上 → 请求关闭
         └─ VcodePanel   居中卡片;拦截指针事件,防止冒泡到遮罩误关
            ├─ VcodeBoard   画布区容器(高度跟随 canvasHeight)
            │  ├─ VcodeCanvasMain     主画布:带拼图缺口的背景图
            │  ├─ VcodeCanvasSuccess  完整图,验证成功时淡入
            │  ├─ VcodeCanvasPuzzle   拼图小块,translateX 跟随滑块
            │  ├─ VcodeLoading        图片加载中的遮罩动画
            │  ├─ VcodeFlash          验证成功时的斜向扫光
            │  ├─ VcodeRefresh        右上角刷新按钮(点击重新生成拼图)
            │  └─ VcodeMessage        结果提示条(绿=成功 / 红=失败)
            └─ VcodeSlider            滑轨容器,含提示文案
               ├─ VcodeSliderProgress 已拖动部分的填充条
               └─ VcodeSliderThumb    可拖拽手柄(mousedown/touchstart 起点)

功能核心 vs 可替换装饰:三个 VcodeCanvas*VcodeSliderProgressVcodeSliderThumb 是状态机直接依赖的功能件(画布要被绘制、progress 元素要被测量、thumb 是拖拽起点),替换它们时必须保留注册/事件契约;Overlay / Panel / Flash / Loading / Message / Refresh 是纯表现层,可随意删改。

模板 ref

VcodeVcodeRoot 暴露同一套实例方法:

// template ref
vcodeRef.value?.reset()
vcodeRef.value?.state // VcodeContext | null(Vcode) / VcodeContext(VcodeRoot)
// Vcode 额外保留 getState() 别名

Headless:useVcode 状态机

连部件都不想用?直接从 @vue-puzzle-vcode/core 拿状态机,自己渲染:

import { useVcode, provideVcodeContext } from '@vue-puzzle-vcode/ui'

// 在根组件 setup 中
const ctx = useVcode(props, {
  onSuccess: (diff) => {},
  onFail: (diff) => {},
  onClose: () => {},
})
provideVcodeContext(ctx) // 之后任意后代组件 useVcodeContext() 取回

返回值为全部响应式状态(pinX / pinY / styleWidth / loading / isSuccess …)、三个 canvas 的 shallowRef 句柄,以及 onThumbDown / onPointerMove / onPointerUp / requestClose / reset 等行为函数。

样式

组件样式与框架解耦,按需引入:

import '@vue-puzzle-vcode/ui/style.css'

所有 class 以 vpv- 为前缀(如 .vpv-overlay.vpv-slider-thumb),方便覆写;组合式用法下也可以完全不管它,全部自己写。

注意

  • 仅浏览器端:依赖 document / canvas / 指针事件,不要在 SSR 阶段渲染;Nuxt 等请 ClientOnly 或动态 import。
  • 纯前端校验:成功事件可在客户端被伪造,只能挡脚本小子与误触,不能替代服务端鉴权。关键操作请再配后端二次校验(token、业务态等)。

License

ISC