{"id":50705814,"url":"https://github.com/liuxin2533/aspect-grid-collageify","last_synced_at":"2026-06-09T12:00:27.902Z","repository":{"id":363063654,"uuid":"1261824051","full_name":"liuxin2533/aspect-grid-collageify","owner":"liuxin2533","description":null,"archived":false,"fork":false,"pushed_at":"2026-06-07T09:51:21.000Z","size":58,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T10:06:16.963Z","etag":null,"topics":["aspect-ratio","canvas","collage","grid","offscreen-rendering","photo-collage","puzzle"],"latest_commit_sha":null,"homepage":"https://liuxin2533.github.io/aspect-grid-collageify/","language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/liuxin2533.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-07T07:41:17.000Z","updated_at":"2026-06-07T09:51:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/liuxin2533/aspect-grid-collageify","commit_stats":null,"previous_names":["liuxin2533/aspect-grid-collageify"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/liuxin2533/aspect-grid-collageify","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liuxin2533%2Faspect-grid-collageify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liuxin2533%2Faspect-grid-collageify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liuxin2533%2Faspect-grid-collageify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liuxin2533%2Faspect-grid-collageify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/liuxin2533","download_url":"https://codeload.github.com/liuxin2533/aspect-grid-collageify/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/liuxin2533%2Faspect-grid-collageify/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34105565,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-09T02:00:06.510Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aspect-ratio","canvas","collage","grid","offscreen-rendering","photo-collage","puzzle"],"created_at":"2026-06-09T12:00:19.445Z","updated_at":"2026-06-09T12:00:27.870Z","avatar_url":"https://github.com/liuxin2533.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# aspect-grid-collageify\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.npmjs.com/package/aspect-grid-collageify\"\u003e\u003cimg src=\"https://img.shields.io/npm/v/aspect-grid-collageify?style=flat-square\u0026color=6366f1\" alt=\"npm version\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/aspect-grid-collageify\"\u003e\u003cimg src=\"https://img.shields.io/npm/dm/aspect-grid-collageify?style=flat-square\u0026color=0ea5e9\" alt=\"npm downloads\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://bundlephobia.com/package/aspect-grid-collageify\"\u003e\u003cimg src=\"https://img.shields.io/bundlephobia/minzip/aspect-grid-collageify?style=flat-square\u0026color=22c55e\" alt=\"minzip size\"\u003e\u003c/a\u003e\n  \u003cimg src=\"https://img.shields.io/badge/TypeScript-ready-3178c6?style=flat-square\" alt=\"TypeScript ready\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/Canvas-powered-f97316?style=flat-square\" alt=\"Canvas powered\"\u003e\n  \u003cimg src=\"https://img.shields.io/badge/sideEffects-false-8b5cf6?style=flat-square\" alt=\"sideEffects false\"\u003e\n  \u003ca href=\"./LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/npm/l/aspect-grid-collageify?style=flat-square\u0026color=10b981\" alt=\"license\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n[English](./README_EN.md) | 简体中文\n\n`aspect-grid-collageify` 是一个轻量级、纯前端、基于 Canvas 的图片拼图工具库。它提供两层能力：\n\n- `CollageCore`：无 UI 的拼图核心，负责状态、网格布局、碰撞检测、图片变更、最终渲染和导出。\n- `CanvasCollageEditor`：基于 `CollageCore` 的可视化编辑器，负责 canvas 交互、选区、拖拽移动、拖拽插入、快捷键和编辑覆盖层。\n\nCore 输出永远是干净的最终拼图；网格线、占位符、选中框、拖拽预览等编辑 UI 只属于 Editor，不会进入导出结果。\n\n## ✨ 特性\n\n- 🎨 纯前端 Canvas 渲染，无服务端依赖。\n- 🖼️ 支持离屏导出 PNG / Blob。\n- 📐 支持自定义容器比例、图片比例、网格列数、间距和内边距。\n- ✨ 支持透明背景、图片圆角、阴影样式。\n- 🧩 支持按网格插入、移动、缩放、交换、删除和替换图片。\n- 🕹️ 支持可视化编辑：点击插槽上传、拖拽文件插入、拖拽移动、拖拽换位、多选、键盘操作。\n- 🧰 鼠标悬浮在已上传图片上时弹出画布内置工具栏：四角方向键移动、右上删除、右下替换、底部 −/+ 缩放；点击图片进入锁定态，工具栏持续显示。\n- 🧠 TypeScript 类型完整导出。\n- 📦 多入口导出，便于只使用 Core 或只引入 Editor。\n\n## 📦 安装\n\n```bash\nnpm install aspect-grid-collageify\n```\n\n```bash\npnpm add aspect-grid-collageify\n```\n\n```bash\nyarn add aspect-grid-collageify\n```\n\n## 🚀 导入方式\n\n推荐按能力入口导入：\n\n```typescript\nimport { CollageCore } from \"aspect-grid-collageify/core\";\nimport { CanvasCollageEditor } from \"aspect-grid-collageify/editor\";\n```\n\n也可以从主入口导入：\n\n```typescript\nimport { CollageCore, CanvasCollageEditor } from \"aspect-grid-collageify\";\n```\n\n| 入口 | 导出 | 说明 |\n| --- | --- | --- |\n| `aspect-grid-collageify` | `CollageCore`, `CanvasCollageEditor`, 全部公共类型 | 主入口。 |\n| `aspect-grid-collageify/core` | `CollageCore` | 只使用离屏渲染和拼图核心能力时使用。 |\n| `aspect-grid-collageify/editor` | `CanvasCollageEditor` | 需要 canvas 可视化编辑能力时使用。 |\n\n## 🖼️ 快速开始：离屏生成拼图\n\n```typescript\nimport { CollageCore } from \"aspect-grid-collageify/core\";\n\nconst core = new CollageCore({\n  containerRatio: \"3:4\",\n  imageRatio: \"16:9\",\n  gridColumns: 8,\n  padding2K: 60,\n  gap2K: 24,\n  background: {\n    color: \"#ffffff\",\n    transparent: false,\n  },\n  imageStyle: {\n    borderRadius2K: 24,\n    shadowBlur2K: 12,\n    shadowOffset2K: 8,\n    shadowOpacity: 0.2,\n  },\n  images: [\n    {\n      id: \"image-1\",\n      src: \"/images/a.jpg\",\n      name: \"A\",\n      gridX: 0,\n      gridY: 0,\n      span: 4,\n    },\n    {\n      id: \"image-2\",\n      src: \"/images/b.jpg\",\n      name: \"B\",\n      gridX: 4,\n      gridY: 0,\n      span: 4,\n    },\n  ],\n});\n\nconst dataUrl = await core.exportPNG(2048);\n```\n\n## 🎛️ 快速开始：可视化编辑器\n\n```typescript\nimport { CollageCore } from \"aspect-grid-collageify/core\";\nimport { CanvasCollageEditor } from \"aspect-grid-collageify/editor\";\n\nconst canvas = document.querySelector(\"canvas\")!;\n\nconst core = new CollageCore({\n  containerRatio: \"3:4\",\n  imageRatio: \"16:9\",\n  gridColumns: 8,\n  padding2K: 60,\n  gap2K: 24,\n  images: [],\n});\n\nconst editor = new CanvasCollageEditor(canvas, core, {\n  multiSelect: true,\n  keyboard: true,\n  dragMove: true,\n  dragSwap: true,\n  dragInsert: true,\n  quickReplace: true,\n});\n\neditor.on(\"change\", (images) =\u003e {\n  console.log(\"images changed\", images);\n});\n\neditor.on(\"cellclick\", (placement) =\u003e {\n  // 调用方可以打开文件选择器，然后调用 editor.insertFiles(files)。\n  editor.setPendingInsertPlacement(placement);\n});\n```\n\n也可以使用便捷构造：\n\n```typescript\nconst editor = CanvasCollageEditor.create(canvas, options, editorOptions);\nconst core = editor.core;\n```\n\n## ⚙️ 配置示例\n\n```typescript\nconst options = {\n  containerRatio: \"3:4\",\n  imageRatio: \"16:9\",\n  gridColumns: 12,\n  padding2K: 60,\n  gap2K: 24,\n  background: {\n    color: \"#ffffff\",\n    transparent: false,\n  },\n  imageStyle: {\n    borderRadius2K: 24,\n    shadowBlur2K: 12,\n    shadowOffset2K: 8,\n    shadowOpacity: 0.2,\n  },\n  placementPreset: \"medium\",\n  images: [],\n};\n```\n\n## 📚 API\n\n### `CollageCore`\n\n`CollageCore` 是拼图状态和最终渲染的核心。它不绑定 DOM 事件，不维护选区，不绘制编辑覆盖层。\n\n#### 构造函数\n\n| API | 位置 | 参数 | 返回值 | 描述 |\n| --- | --- | --- | --- | --- |\n| `new CollageCore(options)` | `aspect-grid-collageify/core` | `options: CollageOptions` | `CollageCore` | 创建一个拼图核心实例，并初始化配置和图片列表。 |\n\n#### 状态 API\n\n| API | 位置 | 参数 | 返回值 | 描述 |\n| --- | --- | --- | --- | --- |\n| `getOptions()` | `CollageCore` | 无 | `CollageOptions` | 获取当前拼图配置。 |\n| `setOptions(options)` | `CollageCore` | `options: CollageOptions` | `void` | 替换完整配置，并触发变更事件。 |\n| `updateOptions(options)` | `CollageCore` | `options: Partial\u003cCollageOptions\u003e` | `void` | 合并更新部分配置，并触发变更事件。 |\n| `getImages()` | `CollageCore` | 无 | `CollageImage[]` | 获取当前图片列表。 |\n| `setImages(images)` | `CollageCore` | `images: CollageImage[]` | `void` | 替换图片列表；会根据当前网格列数约束图片位置。 |\n| `onChange(callback)` | `CollageCore` | `callback: (images: CollageImage[], options: CollageOptions) =\u003e void` | `Unsubscribe` | 监听配置或图片变化。返回取消监听函数。 |\n| `destroy()` | `CollageCore` | 无 | `void` | 清理监听器和图片缓存。 |\n\n#### 几何 API\n\n| API | 位置 | 参数 | 返回值 | 描述 |\n| --- | --- | --- | --- | --- |\n| `getLayout(width, height)` | `CollageCore` | `width: number`, `height: number` | `CollageLayout` | 根据视口尺寸和当前配置计算布局。 |\n| `toGridPoint(point, viewport)` | `CollageCore` | `point: GridPoint`, `viewport: DrawViewport` | `GridPoint` | 将 canvas 坐标转换为网格坐标。 |\n| `getImageRect(imageOrId, layout)` | `CollageCore` | `imageOrId: CollageImage \\| string`, `layout: CollageLayout` | `ImageRect \\| null` | 获取指定图片在 canvas 中的矩形区域。 |\n| `hitTest(point, viewport)` | `CollageCore` | `point: GridPoint`, `viewport: DrawViewport` | `CollageImage \\| null` | 根据 canvas 坐标命中图片。 |\n| `getPlacementSpan(preset?)` | `CollageCore` | `preset?: PlacementPreset` | `number` | 根据当前网格列数和预设计算插入图片的 span。 |\n| `findSlots(options)` | `CollageCore` | `options: FindSlotsOptions` | `GridPlacement[]` | 查找当前布局中可放置图片的空插槽。 |\n| `findFirstSlot(options)` | `CollageCore` | `options: FindSlotsOptions` | `GridPlacement \\| null` | 查找第一个可用空插槽。 |\n| `canPlace(placement, gridRows, ignoreIds?)` | `CollageCore` | `placement: GridPlacement`, `gridRows: number`, `ignoreIds?: string[]` | `boolean` | 判断指定位置是否可放置图片，可忽略指定图片 id。 |\n\n#### 图片与布局 API\n\n| API | 位置 | 参数 | 返回值 | 描述 |\n| --- | --- | --- | --- | --- |\n| `insertImage(image)` | `CollageCore` | `image: CollageImage` | `CollageImage` | 插入完整图片对象。调用方负责提供 id、src、gridX、gridY 和 span。 |\n| `insertImageAt(input, placement)` | `CollageCore` | `input: ImageInput`, `placement: GridPlacement` | `CollageImage` | 根据图片输入和明确位置创建并插入图片。 |\n| `insertImages(inputs, options)` | `CollageCore` | `inputs: ImageInput[]`, `options: InsertImagesOptions` | `CollageImage[]` | 批量插入图片，按空插槽自动排布。 |\n| `updateImage(id, patch)` | `CollageCore` | `id: string`, `patch: Partial\u003cCollageImage\u003e` | `boolean` | 更新指定图片。成功返回 `true`。 |\n| `removeImage(id)` | `CollageCore` | `id: string` | `boolean` | 删除单张图片。成功返回 `true`。 |\n| `removeImages(ids)` | `CollageCore` | `ids: string[]` | `boolean` | 批量删除图片。成功返回 `true`。 |\n| `replaceImage(id, input)` | `CollageCore` | `id: string`, `input: ImageInput` | `boolean` | 替换指定图片的 src、name 和样式。 |\n| `moveImage(id, target, gridRows)` | `CollageCore` | `id: string`, `target: GridPoint`, `gridRows: number` | `boolean` | 将单张图片移动到指定网格坐标。 |\n| `moveImages(ids, delta, gridRows)` | `CollageCore` | `ids: string[]`, `delta: GridPoint`, `gridRows: number` | `boolean` | 按网格偏移量批量移动图片。 |\n| `moveImagesByDirection(ids, direction, gridRows)` | `CollageCore` | `ids: string[]`, `direction: MoveDirection`, `gridRows: number` | `boolean` | 按方向批量移动图片。 |\n| `resizeImage(id, delta, gridRows)` | `CollageCore` | `id: string`, `delta: number`, `gridRows: number` | `boolean` | 调整单张图片 span。 |\n| `resizeImages(ids, delta, gridRows)` | `CollageCore` | `ids: string[]`, `delta: number`, `gridRows: number` | `boolean` | 批量调整图片 span。 |\n| `swapImages(sourceId, targetId)` | `CollageCore` | `sourceId: string`, `targetId: string` | `boolean` | 交换两张图片的位置和 span。 |\n| `pushBelow(id, rows, gridRows)` | `CollageCore` | `id: string`, `rows: number`, `gridRows: number` | `boolean` | 将指定图片下方的图片整体向下推。 |\n| `pullBelow(id, rows?)` | `CollageCore` | `id: string`, `rows?: number` | `boolean` | 将指定图片下方的图片整体向上拉。 |\n\n#### 渲染与导出 API\n\n| API | 位置 | 参数 | 返回值 | 描述 |\n| --- | --- | --- | --- | --- |\n| `draw(ctx, viewport)` | `CollageCore` | `ctx: CanvasRenderingContext2D`, `viewport: DrawViewport` | `void` | 在指定 canvas 上绘制最终拼图。 |\n| `renderToCanvas(width?)` | `CollageCore` | `width?: number` | `Promise\u003cHTMLCanvasElement\u003e` | 离屏渲染并返回 canvas。高度由容器比例自动计算。 |\n| `exportPNG(width?)` | `CollageCore` | `width?: number` | `Promise\u003cstring\u003e` | 导出 PNG Data URL。 |\n| `exportBlob(width?, type?, quality?)` | `CollageCore` | `width?: number`, `type?: string`, `quality?: number` | `Promise\u003cBlob\u003e` | 导出 Blob。支持 PNG、JPEG、WebP 等 canvas 支持的类型。 |\n| `getImageLoader()` | `CollageCore` | 无 | `ImageLoader` | 获取内部图片加载器。通常仅高级场景使用。 |\n\n### `CanvasCollageEditor`\n\n`CanvasCollageEditor` 是 canvas 可视化编辑引擎。它通过 `core` 读写拼图状态，并额外维护选区、活动图片、拖拽状态和编辑覆盖层。\n\n#### 构造函数\n\n| API | 位置 | 参数 | 返回值 | 描述 |\n| --- | --- | --- | --- | --- |\n| `new CanvasCollageEditor(canvas, core, options?)` | `aspect-grid-collageify/editor` | `canvas: HTMLCanvasElement`, `core: CollageCore`, `options?: CanvasCollageEditorOptions` | `CanvasCollageEditor` | 基于已有 Core 创建可视化编辑器。 |\n| `CanvasCollageEditor.create(canvas, options, editorOptions?)` | `CanvasCollageEditor` | `canvas: HTMLCanvasElement`, `options: CollageOptions`, `editorOptions?: CanvasCollageEditorOptions` | `CanvasCollageEditor` | 便捷构造：内部创建 `CollageCore` 并返回 editor。 |\n\n#### 基础 API\n\n| API | 位置 | 参数 | 返回值 | 描述 |\n| --- | --- | --- | --- | --- |\n| `core` | `CanvasCollageEditor` | 无 | `CollageCore` | 底层 Core 实例。 |\n| `getCore()` | `CanvasCollageEditor` | 无 | `CollageCore` | 获取底层 Core 实例。 |\n| `render()` | `CanvasCollageEditor` | 无 | `void` | 重绘最终拼图和编辑覆盖层。 |\n| `resize()` | `CanvasCollageEditor` | 无 | `void` | 根据 canvas 当前尺寸重新渲染。 |\n| `destroy()` | `CanvasCollageEditor` | 无 | `void` | 移除事件监听并释放由 editor 创建的 Object URL。 |\n\n#### 选区 API\n\n| API | 位置 | 参数 | 返回值 | 描述 |\n| --- | --- | --- | --- | --- |\n| `getSelection()` | `CanvasCollageEditor` | 无 | `string[]` | 获取当前选中的图片 id 列表。 |\n| `setSelection(ids)` | `CanvasCollageEditor` | `ids: string[]` | `void` | 设置选区。无效 id 会被忽略。 |\n| `getActiveId()` | `CanvasCollageEditor` | 无 | `string \\| null` | 获取当前活动图片 id。 |\n| `setActiveId(id)` | `CanvasCollageEditor` | `id: string \\| null` | `void` | 设置当前活动图片，并同步选区。 |\n| `clearSelection()` | `CanvasCollageEditor` | 无 | `void` | 清空选区和活动图片。 |\n\n#### 输入与文件 API\n\n| API | 位置 | 参数 | 返回值 | 描述 |\n| --- | --- | --- | --- | --- |\n| `handleKeyDown(event)` | `CanvasCollageEditor` | `event: KeyboardEvent` | `boolean` | 处理删除、方向移动、快捷缩放等键盘操作。 |\n| `insertFiles(files, options?)` | `CanvasCollageEditor` | `files: FileList \\| File[]`, `options?: Partial\u003cInsertImagesOptions\u003e` | `Promise\u003cCollageImage[]\u003e` | 解析并插入文件。若存在 pending placement，则优先插入该位置。 |\n| `insertFilesAt(files, point)` | `CanvasCollageEditor` | `files: FileList \\| File[]`, `point: GridPoint` | `Promise\u003cCollageImage[]\u003e` | 按 canvas 坐标插入文件；优先命中空插槽，否则回退到网格落点。 |\n| `replaceActiveFile(file)` | `CanvasCollageEditor` | `file: File` | `Promise\u003cboolean\u003e` | 用文件替换当前活动图片。 |\n| `replaceFile(id, file)` | `CanvasCollageEditor` | `id: string`, `file: File` | `Promise\u003cboolean\u003e` | 用文件替换指定图片。 |\n| `setPendingInsertPlacement(placement)` | `CanvasCollageEditor` | `placement: GridPlacement \\| null` | `void` | 设置下一次 `insertFiles()` 优先使用的插入位置。 |\n\n#### 事件 API\n\n| API | 位置 | 参数 | 返回值 | 描述 |\n| --- | --- | --- | --- | --- |\n| `on(\"change\", callback)` | `CanvasCollageEditor` | `callback: (images: CollageImage[]) =\u003e void` | `Unsubscribe` | Core 变化并完成 editor 重绘后触发。 |\n| `on(\"selectionchange\", callback)` | `CanvasCollageEditor` | `callback: (ids: string[]) =\u003e void` | `Unsubscribe` | 选区变化时触发。 |\n| `on(\"activechange\", callback)` | `CanvasCollageEditor` | `callback: (id: string \\| null) =\u003e void` | `Unsubscribe` | 活动图片变化时触发。 |\n| `on(\"cellclick\", callback)` | `CanvasCollageEditor` | `callback: (placement: GridPlacement) =\u003e void` | `Unsubscribe` | 点击空插槽时触发。 |\n| `on(\"replacerequest\", callback)` | `CanvasCollageEditor` | `callback: (id: string) =\u003e void` | `Unsubscribe` | 双击图片请求替换时触发。 |\n| `on(\"error\", callback)` | `CanvasCollageEditor` | `callback: (error: unknown) =\u003e void` | `Unsubscribe` | 文件解析、拖拽插入等异步错误发生时触发。 |\n\n### 类型 API\n\n#### 基础类型\n\n| 类型 | 位置 | 字段 / 参数 | 描述 |\n| --- | --- | --- | --- |\n| `RatioOption` | `aspect-grid-collageify` | `\"1:1\" \\| \"3:4\" \\| \"4:3\" \\| \"16:9\" \\| \"9:16\" \\| \"custom\" \\| string` | 比例配置。普通字符串应为 `w:h` 格式。 |\n| `PlacementPreset` | `aspect-grid-collageify` | `\"small\" \\| \"medium\" \\| \"large\"` | 自动插入图片时使用的尺寸预设。 |\n| `MoveDirection` | `aspect-grid-collageify` | `\"up\" \\| \"down\" \\| \"left\" \\| \"right\"` | 方向移动枚举。 |\n| `GridPoint` | `aspect-grid-collageify` | `{ x: number; y: number }` | 网格点或 canvas 点。语义由 API 参数决定。 |\n| `GridPlacement` | `aspect-grid-collageify` | `{ gridX: number; gridY: number; span: number }` | 图片在网格中的位置和尺寸。 |\n| `ViewportSize` | `aspect-grid-collageify` | `{ width: number; height: number }` | 视口尺寸。 |\n| `DrawViewport` | `aspect-grid-collageify` | `{ width: number; height: number }` | 绘制视口尺寸。 |\n| `Unsubscribe` | `aspect-grid-collageify` | `() =\u003e void` | 取消监听函数。 |\n\n#### 配置与图片类型\n\n| 类型 | 位置 | 字段 / 参数 | 描述 |\n| --- | --- | --- | --- |\n| `ImageStyleOptions` | `aspect-grid-collageify` | `borderRadius2K?: number`, `shadowBlur2K?: number`, `shadowOffset2K?: number`, `shadowOpacity?: number` | 图片样式配置。数值以 2K 画布为基准缩放。 |\n| `CollageImage` | `aspect-grid-collageify` | `id: string`, `src: string`, `name: string`, `gridX: number`, `gridY: number`, `span: number`, `ImageStyleOptions` | 拼图中的图片模型。 |\n| `ImageInput` | `aspect-grid-collageify` | `id?: string`, `src: string`, `name?: string`, `style?: ImageStyleOptions` | 插入或替换图片时的输入模型。 |\n| `CollageOptions` | `aspect-grid-collageify` | `containerRatio`, `imageRatio`, `gridColumns`, `padding2K`, `gap2K`, `background?`, `imageStyle?`, `images?`, `placementPreset?` | 拼图核心配置。 |\n\n#### 布局与操作类型\n\n| 类型 | 位置 | 字段 / 参数 | 描述 |\n| --- | --- | --- | --- |\n| `CollageLayout` | `aspect-grid-collageify` | `scale`, `padding`, `gap`, `cellW`, `cellH`, `gridRows`, `offsetX`, `offsetY`, `gridW`, `gridH`, `containerRatioVal`, `imageRatioVal` | 根据配置和视口计算出的布局数据。 |\n| `ImageRect` | `aspect-grid-collageify` | `{ x: number; y: number; w: number; h: number }` | 图片在 canvas 中的矩形区域。 |\n| `FindSlotsOptions` | `aspect-grid-collageify` | `{ span: number; gridRows: number }` | 查找空插槽的参数。 |\n| `InsertImagesOptions` | `aspect-grid-collageify` | `{ span?: number; placementPreset?: PlacementPreset; gridRows: number }` | 批量插入图片的参数。 |\n| `CanvasCollageEditorOptions` | `aspect-grid-collageify/editor` | `multiSelect?`, `keyboard?`, `dragMove?`, `dragSwap?`, `dragInsert?`, `quickReplace?`, `preventDefaultFileDrop?`, `fileResolver?`, `overlay?` | Editor 交互配置。 |\n| `EditorOverlayOptions` | `aspect-grid-collageify` | `showBoundary?`, `showGridlines?`, `showSlots?`, `slotText?` | Editor 覆盖层显示配置。 |\n\n## 🛠️ 本地开发\n\n```bash\npnpm install\npnpm dev\n```\n\n打开 demo 页面后可以测试 canvas 可视化编辑能力。\n\n构建发布产物：\n\n```bash\npnpm build\n```\n\n当前构建会输出 ESM、CommonJS 和类型声明，并支持以下包入口：\n\n```text\naspect-grid-collageify\naspect-grid-collageify/core\naspect-grid-collageify/editor\n```\n\n## 🗂️ 目录结构\n\n```text\nsrc/\n  core.ts           # CollageCore：状态、几何、布局变更、最终渲染和导出\n  editor.ts         # CanvasCollageEditor：canvas 可视化编辑能力\n  editor-render.ts  # 编辑覆盖层渲染\n  image-loader.ts   # 图片加载和缓存\n  layout.ts         # 纯几何、网格、碰撞、空位查找\n  render.ts         # 最终拼图渲染\n  types.ts          # 公共类型\n  index.ts          # 主导出入口\n```\n\n## 📄 协议\n\n本项目使用 [MIT License](./LICENSE)。\n\nCopyright (c) 2026 liuxin2533","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliuxin2533%2Faspect-grid-collageify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fliuxin2533%2Faspect-grid-collageify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliuxin2533%2Faspect-grid-collageify/lists"}