游乐游手机版
首页/前端开发/文章详情

Vue 3可视化打印模板设计器 print-canvas-designer

时间:2026-06-17 06:51
Vue3打印模板设计器面向标签、鞋盒标等场景,提供文本、图片、二维码等组件,支持拖拽缩放、旋转、层级调整等编辑功能。支持自定义业务组件及属性编辑,提供完整编辑器、自定义组件、仅画布三种接入方式,模板数据与业务数据分离,便于自由排版与持续维护。

用 Vue3 打造可扩展的打印模板设计器,灵活应对标签排版

在企业级业务系统中,标签打印最常见的难题并非一次性输出功能,而是一套需要持续迭代的编辑能力。

例如,鞋盒标通常需要展示款号、颜色、尺码、品牌图片、条形码和二维码——单看元素并不复杂。但现实是,不同客户对布局的要求各不相同,即使同一客户也可能后期调整模板。如果全靠开发人员在页面上固定位置,每次排版变更都要重新发版,迭代效率无疑会大打折扣。

因此,清晰的解决思路是:

基于这一目标,我开发了一款 Vue 3 打印模板画布组件:print-canvas-designer,并配套了真实接入示例项目 print-canvas-examples,内含演示和参考文档。

它解决了哪些痛点

print-canvas-designer 主要适用于标签、鞋盒标、物流面单、商品贴纸等需要自由排版的打印场景。

当前版本支持的能力清单如下:

  • 文本、图片、矩形、横线、二维码、条形码等基础组件。
  • A4、100 x 60 以及自定义纸张尺寸。
  • 元素选中、拖拽、缩放、旋转、复制、删除、锁定、隐藏、层级调整。
  • 标尺、网格、参考线、页边距、安全区和缩放控制。
  • 文本字段渲染和换行策略。
  • 图片地址设置,支持通过业务上传方法写入图片地址。
  • 打印和导出 PDF。
  • 自定义业务组件及对应的属性编辑区域。
  • 支持完整编辑器接入,也可以只接入画布、自行搭建外围 UI。

需要特别指出:打印设计器的核心并非固定的左侧面板或右侧表单,而是画布本身。不同业务对组件和属性的需求差异极大,因此画布只提供基础编辑能力,具体需要呈现哪些组件,交由业务自行决定。

三种接入方式

为了演示 npm 包在真实 Vue3 项目里的接入方式,print-canvas-examples 提供了三类场景:

  1. 完整编辑器:直接使用默认的工具栏、组件面板、画布与属性面板。
  2. 自定义业务组件:将鞋盒标信息块作为业务组件注册到画布。
  3. 只接入画布:左侧组件区、顶部工具栏、右侧属性区全部由业务项目自己实现。

在线示例(点我)

快速上手:使用完整编辑器

安装依赖:

npm install print-canvas-designer

在入口文件引入样式:

import 'print-canvas-designer/style.css'

页面中使用完整编辑器:


v-model 绑定的就是模板数据。业务系统可以将这份 JSON 保存到数据库,后续重新传给组件即可还原模板。

为何支持只接入画布

完整编辑器适合快速集成,但在真实项目里,已有系统通常拥有自己的页面布局和交互方式:

  • 左侧可能不是基础组件列表,而是“商品字段”“订单字段”“客户 Logo”等业务物料。
  • 右侧可能需要结合权限、表单校验、字段绑定以及业务规则。
  • 顶部操作区可能需要与系统现有的保存、审核、发布流程对接。

此时仅接入 PrintCanvas 就派上用场了,页面的整体结构完全由业务自主掌控。


面板和画布之间通过同一个 designer 实例通信。例如,选中元素后,业务属性表单可以调用:

designer.updateElement(activeId, { field: 'styleColorSize' })
designer.updateElementStyle(activeId, { width: 200, height: 42 })
designer.removeElement(activeId)
designer.undo()
designer.redo()
designer.sa ve()

这样一来,画布负责编辑交互,业务系统负责 UI 和数据规则,分工清晰明确。

自定义组件:以鞋盒标信息块为例

基础文本组件已经可以通过字段渲染业务内容,但有些重复出现、结构固定的区域,更适合封装成业务组件。

比如鞋盒标中的商品信息区域,通常固定包含:

  • 标题,例如 SPORT SERIES
  • 主内容,例如 RUNNER-01 / BLACK / 42
  • 副内容,例如 STYLE / COLOR / SIZE
  • 强调颜色或品牌样式。

业务可以定义一个组件,在画布中负责展示结构,同时为它提供独立的属性编辑 UI。组件内容、业务字段和表单交互由业务自行实现,画布仍然提供选中、移动、缩放、旋转、删除和保存等基础能力。

import {
  defaultPrintComponents,
  type PrintComponentDefinition
} from 'print-canvas-designer'
import ShoeInfoBlockRender from './ShoeInfoBlockRender.vue'
import ShoeInfoBlockInspector from './ShoeInfoBlockInspector.vue'const shoeInfoBlock: PrintComponentDefinition = {
  type: 'shoe-info-block',
  label: '鞋盒标信息块',
  icon: 'i-lucide-tag',
  render: ShoeInfoBlockRender,
  inspector: ShoeInfoBlockInspector,
  createElement: (point) => ({
    id: `shoe_${Date.now()}`,
    type: 'shoe-info-block',
    name: '鞋盒标信息块',
    props: {
      title: 'SPORT SERIES',
      mainText: 'RUNNER-01 / BLACK / 42',
      subText: 'STYLE / COLOR / SIZE',
      accentColor: '#2563eb'
    },
    style: {
      position: 'absolute',
      left: point.x,
      top: point.y,
      width: 260,
      height: 92,
      rotate: 0
    }
  })
}export const components = [
  ...defaultPrintComponents,
  shoeInfoBlock
]

将其传给完整编辑器,即可在物料列表和画布中使用:


在只接入画布的模式下,也可以将同样的 components 传给 createPrintDesigner。也就是说,自定义组件并不仅仅是完整编辑器才有的能力,而是画布 SDK 提供给业务的扩展机制。

模板数据与业务数据如何协同

模板本身保存的是布局与元素配置,实际打印数据则在运行时传入。

以文本为例,模板中可以保存字段名:

{
  "type": "text",
  "name": "款色码",
  "field": "styleColorSize",
  "style": {
    "left": 24,
    "top": 32,
    "width": 220,
    "height": 42
  }
}

业务在打印前把多个字段拼接为需要展示的内容:

const printData = {
  styleColorSize: [product.style, product.color, product.size].join(' / ')
}

这种方式让画布保持通用,不必为每一种业务字段组合设计专门的布局规则。

图片、打印与导出

图片组件既可以直接填写图片地址,也可以将上传过程交给业务系统:

const uploadImage = async (file: File) => {
  const url = await uploadToObjectStorage(file)
  return url
}

输出方面,完整编辑器提供了打印和导出 PDF 的交互入口。只接入画布时,也可以通过 designer.print()designer.exportPdf() 接入自己的操作入口和输出流程。

当前阶段与后续计划

当前版本主要聚焦于打印模板画布的核心能力,以及业务扩展所需的组件机制。已经可以用于搭建标签类模板并验证实际接入方式。

后续计划继续完善的方向:

  • 更丰富的自定义业务组件示例。
  • 模板管理、保存与复用场景的参考实现。
  • 打印与导出流程在真实业务中的接入示例。

相关地址

  • npm
  • 文档
  • 画布演示
  • Vue3 集成示例
  • GitHub
来源:https://juejin.cn/post/7644872938174267392
上一篇后端告别手绘!TinyVue流程图组件跨端定制指南 下一篇后台权限系统架构设计与Vue3/React双框架落地实践
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
如何在JavaScript中实现基于旋转视野的FOV射线绘制详解
前端开发 · 2026-07-01

如何在JavaScript中实现基于旋转视野的FOV射线绘制详解

如果用一句话概括核心,那就是:在 RayCasting 游戏开发中,绘制动态视野边界线(FOV)最可靠的方式是在逻辑层通过数学公式将坐标“算”出来,而不是依赖 Canvas 绘图上下文的旋转操作。 在实现类似 Doom 风格的 RayCasting 游戏时,动态视野(Field of View, F

TypeScript后端数据正确映射为前端接口类型的方法
前端开发 · 2026-07-01

TypeScript后端数据正确映射为前端接口类型的方法

在后端数据与前端类型之间来回转换,几乎是每位 TypeScript 开发者都无法回避的常态。后端返回的 car_brand、reg_number,和前端接口中定义的 brand、govtNumber,命名风格常常对不上号。此时,如果为了省事直接用 as 类型断言“强行”指认类型,那就踩进了常见的陷阱

动态HTML表格按层级条件合并单元格的JavaScript实现
前端开发 · 2026-07-01

动态HTML表格按层级条件合并单元格的JavaScript实现

本文详细讲解一种递归式 JavaScript 合并单元格方法,用于按列优先级(如前3列)智能合并表格行:仅当前一列已合并的前提下,才允许后续列合并相同值,从而精准实现多级分组与层级表格合并效果。 在动态生成的 HTML 表格中,按业务逻辑合并重复行是常见需求。然而,简单地对单列分别遍历合并——例如先

Next.js 13+重定向后滚动失效解决方案
前端开发 · 2026-07-01

Next.js 13+重定向后滚动失效解决方案

在 Next js App Router 的日常开发中,有一个令人颇为困扰的异常现象——当服务端执行 `redirect()` 跳转后,目标页面竟然无法正常滚动。没错,页面已经渲染完成,内容也完整显示,但垂直滚动条仿佛凭空消失。这个问题在 Next js 13 5 4 版本中尤为突出。 先给出结论:

WebGL图像加载延迟的纹理初始化时立即显示方法
前端开发 · 2026-07-01

WebGL图像加载延迟的纹理初始化时立即显示方法

本文详细介绍如何利用 Promise 与 async await 重构 WebGL 纹理加载流程,彻底解决首次渲染显示蓝色占位色、需要手动交互才能刷新的问题,实现文件导入后四张纹理平面即时正确渲染。 实际上,这个坑在 WebGL 开发中相当常见——纹理异步加载的小陷阱,说起来不大,但第一次遇到确实令