beauty-pack-generator
v1.0.0
Published
美颜资源包生成器 - Canvas 对齐核心 API
Downloads
1,455
Readme
beauty-pack-generator
美颜资源包生成器 —— 基于 Vite + 原生 JS + Fabric.js 的 Canvas 对齐核心库,支持多素材叠加、锚点校准与 3D 预览。
项目结构
- 根目录:可发布的 ESM 库(纯 API,无上传/导出 UI)
demo/:宿主调试应用(完整的侧栏 UI + 导出流程)
Demo 功能
- 示例按钮 — 示例一/二/三按钮,点击一次添加一次素材(可重复);自动应用预设位置/缩放,默认与镜像素材各自独立预设
- 锚点类型快速切换 — 素材列表中通过自定义下拉菜单(非原生 select)直接更改锚点类型,无需重新导入
- 锚点参考点 — 嘴巴锚点使用左右嘴角(96/100)参考点
完整接入文档
各框架(Vue / React / 原生 JS)的完整接入示例、组件代码、API 详解请参见:
快速开始
构建库
npm install
npm run build启动 Demo
cd demo
npm install
npm run dev或根目录:
npm run dev库 API
import { BeautyPackGenerator } from 'beauty-pack-generator'
const generator = new BeautyPackGenerator({
container: document.getElementById('canvas-container'),
onReady: () => {},
onError: (err) => {},
})
await generator.importImage(file, 'eye') // 导入素材并指定锚点类型
generator.calibrateAnchors() // 校准锚点到 UV 参考位置
generator.setMaterialFlipped(0, true) // 水平翻转素材(镜像),反转后自动校准锚点
await generator.export({ name: 'my-pack', encrypt: false }) // 导出资源包
await generator.exportPreview() // 导出预览图(人物底图+贴纸,PNG)
generator.destroy()
// 独立加密已有 ZIP(不依赖实例)
import { encryptZip } from 'beauty-pack-generator'
const gpresBlob = await encryptZip(zipFile, { autoDownload: true })核心功能
- 多素材叠加 — 多次调用
importImage()叠加素材到画布,每个素材独立变换 - 锚点系统 — 支持 4 种锚点类型(眉毛/眼睛/鼻子/嘴巴),素材列表可通过自定义下拉菜单直接修改锚点类型
- 自动校准 — 拖拽素材后自动将锚点对齐到 UV 参考位置
- 下层拖拽 — 双击切换选中下层素材后,直接拖拽即可操作,不受上层素材遮挡影响
- 图层管理 — 素材列表拖拽排序;双击画布按层级轮流切换重叠素材;支持显隐控制
- 锁定保护 — 每个素材独立锁定,防止误编辑和误选
- 水平翻转 — 每个素材独立左右镜像,反转后自动校准锚点,全链路生效(画布 / 导出 / 3D 预览)
- 镜像编辑 — 默认/镜像双列表,镜像素材自动反转;切换列表后画布只显示当前列表;删除双向联动;默认/镜像统一排序(两列表顺序始终一致);导出按
default/、mirror/分组 - 光标交互 — 悬停素材显示抓取手 🖐,拖拽时显示握拳 ✊;画布平移时同步显示手型
- UV 参考网格 — 1280×1280 灰底网格线辅助定位,支持独立显隐开关
- 底图裁切 — 背景图自动裁切到 1280×1280 UV 区域内,超出部分隐藏
- GIF 支持 — 解码 GIF 帧动画,导出时拆帧为 PNG
- 3D 预览 — 右上角实时预览素材在 3D 模型上的效果,深色底色,只渲染可见素材
- 资源导出 — 导出为 ZIP 或 AES-256-GCM 加密的
.gpres格式,JSON 包含素材宽高;导出图片保留画布上的旋转和缩放
构造函数选项
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
| container | HTMLElement | 必填 | Canvas 挂载容器 |
| fitPadding | number | 0.04 | 人脸适配边距 |
| showLandmarks | boolean | false | 显示人脸标注点 |
| showLandmarkLabels | boolean | true | 显示标注点索引 |
| modelPreviewWidth | number | 280 | 3D 预览宽度 |
| modelPreviewHeight | number | 320 | 3D 预览高度 |
| modelAutoRotate | boolean | false | 3D 预览自动旋转 |
回调钩子
| 回调 | 签名 | 说明 |
|------|------|------|
| onReady | () => void | 初始化完成 |
| onImageLoaded | (meta: object) => void | 素材加载完成 |
| onTransformChange | (transform: object) => void | 素材变换变更 |
| onLandmarkHover | (info: object \| null) => void | 标注点悬停 |
| onLandmarkSelect | (info: object \| null) => void | 标注点选中 |
| onError | (error: Error) => void | 错误处理 |
| onViewportChange | (viewport: object) => void | 视口变更 |
| onActiveMaterialChange | (index: number) => void | 活跃素材切换 |
| onAnchorChange | (anchors: Array) => void | 锚点数据变更 |
方法
素材管理
| 方法 | 说明 |
|------|------|
| importImage(file, anchorTypeId?) | 导入素材,可指定锚点类型 |
| getMaterials() | 获取所有素材信息列表(含 visible/anchorTypeId/flipped) |
| setActiveMaterial(index) | 选中指定素材 |
| removeMaterial(index) | 删除指定素材 |
| reorderMaterial(fromIdx, toIdx) | 拖拽排序素材 |
| setMaterialVisibility(index, visible) | 设置素材显隐 |
| setMaterialFlipped(index, flipped) | 设置素材水平翻转(左右镜像),反转后自动校准锚点 |
| switchEditList(list) | 切换编辑列表:'default' 默认 / 'mirror' 镜像,切换后画布只显示当前列表 |
| getEditList() | 获取当前编辑列表:'default' / 'mirror' |
| resetTransform() | 重置素材变换为居中初始状态 |
锚点
| 方法 | 说明 |
|------|------|
| setAnchorType(typeId) | 设置当前素材锚点类型(eyebrow/eye/nose/mouth),传 null 清除 |
| setMaterialAnchorType(index, typeId) | 设置指定素材的锚点类型 |
| calibrateAnchors() | 校准锚点到 UV 参考位置(素材不动) |
| setMaterialLocked(index, locked) | 锁定/解锁单个素材的编辑和选中 |
| calibrateAllAnchors() | 一键校准所有素材锚点 |
| setAutoCalibrate(enabled) | 设置拖拽后自动校准 |
| getAnchorData() | 获取当前素材锚点数据 |
画布
| 方法 | 说明 |
|------|------|
| zoomIn() / zoomOut() | 缩放画布 |
| resetView() | 重置视图 |
| getZoom() | 获取当前缩放倍率 |
| screenToCanvas() / canvasToScreen() | 坐标转换 |
| screenToUV() / uvToScreen() | UV 坐标转换 |
显示
| 方法 | 说明 |
|------|------|
| setLandmarksVisible(visible) | 标注点显隐 |
| setLandmarkLabelsVisible(visible) | 索引标签显隐 |
| setMeshVisible(visible) | 人脸三角网格显隐 |
| setUvGridVisible(visible) | UV 参考网格(1280×1280 灰底 + 网格线)显隐 |
3D 预览
| 方法 | 说明 |
|------|------|
| showModelPreview() / hideModelPreview() | 显隐 3D 预览 |
| toggleModelPreview() | 切换显隐 |
| setModelAutoRotate(enabled) | 设置自动旋转 |
导出
| 方法 | 说明 |
|------|------|
| export(options?) | 导出资源包(ZIP / 加密 .gpres) |
| exportPreview(fileName?, options?) | 导出预览图 PNG(默认 320×320,可传 { width, height } 自定义分辨率;人物底图+贴纸组合,自动下载) |
| encryptZip(zipBlob, options?) | 独立加密 ZIP → .gpres(不依赖实例) |
| getState() | 获取完整状态信息 |
生命周期
| 方法 | 说明 |
|------|------|
| destroy() | 销毁实例,释放所有资源 |
导出配置
await generator.export({
name: 'my-pack', // 资源包名称,默认 'export'
encrypt: true, // 是否 AES-256-GCM 加密,默认 true
})- 加密导出 →
.gpres文件 - 普通导出 →
.zip文件
双坐标系
| 空间 | 尺寸 | 用途 | |------|------|------| | 参考空间 | 固定 1280×1280 | 人脸点位、网格、素材变换、导出坐标 | | 显示空间 | 宿主容器尺寸 | 可见 Canvas 像素尺寸 |
内部通过 Fabric viewport 将 1280 参考空间适配到显示画布,导出坐标始终基于参考空间。
数据导出(资源包 JSON)
{
"version": 1.2,
"id": "export",
"layers": {
"default": [
{
"type": 999,
"name": "0",
"width": 1084,
"height": 1280,
"lockPoint": [104, 105],
"lockPointMappingInPixel": [[301.65, 397.52], [782.35, 397.52]]
}
],
"mirror": []
}
}width/height— 导出 PNG 的实际像素尺寸(含旋转后的包围盒)lockPointMappingInPixel— 锚点在导出 PNG 上的像素坐标(已计入缩放和旋转)- 资源按
{group}/{layerName}/{fileName}存放,如default/0/0.png、mirror/1/frame_00_delay-0.1s.png - 镜像编辑开关未勾选时跳过镜像相关导出(
layers.mirror为空,不生成mirror/文件夹)
命名导出
除主类外,库还导出:
FACE_LANDMARKS/FACE_LANDMARK_COUNT/FACE_LANDMARK_REGIONS— 人脸标注数据FACE_MESH_INDICES/getFaceLandmarkBounds()/getLandmarkRegion()/getMeshEdges()— 网格工具landmarkToPixel()/landmarkUvToPixel()— 坐标转换REFERENCE_WIDTH/REFERENCE_HEIGHT— 参考空间常量DEFAULT_FIT_PADDING/DEFAULT_OVERLAY_SCALE— 默认配置computeFitViewport()/getEffectiveCanvasSize()— 视口工具encryptToGpres()— AES-256-GCM 加密工具
