资讯动态

T恤DIY定制系统源码解析:从Canvas画布交互到SKU订单落地

发布时间:2026/10/18 17:16:38 来源:尧图企业网站定制
简介面向手机端的T恤DIY定制系统项目压缩包定位于为前端开发者、独立设计师及电商二次开发人员提供一套可扩展的在线T恤定制交互原型。系统以HTML5 canvas为绘制核心通过模板选择、文字与图形叠加等操作实现个性化设计并对canvas与文字合成、字体加载、交互反馈等关键环节给出了可继续完善的基础结构。压缩包整体约14.19MB包含页面入口、JS逻辑、CSS样式、图片素材与字体文件等目录便于按模块拆解与改造。目前已有797人学习下载。读者可获得一套完整的T恤DIY设计前端工程雏形包括拖拽/选择类交互逻辑、canvas绘图思路、多字体方案及模板资源配置方式尤其适合需要快速搭建定制类电商前台或深入学习canvas交互开发的进阶学习者。1. T恤DIY定制系统一套能直接落地的设计交互源码做定制类电商的人应该都有同感——T恤DIY这个品类难的不是后端下单而是前端那个“让用户自己动手设计”的交互过程。素材拖拽、文字编辑、图层叠加、价格联动任何一个环节卡顿或逻辑混乱用户都会直接放弃下单。这套T恤DIY定制系统源码解决的就是从“用户上传图片”到“生成可下单的定制T恤”这条完整链路。它不是一个纯展示的Demo而是包含设计画布、实时预览、SKU联动计价、订单数据落库的完整方案。适合正在做定制类商城、对前端交互有一定基础、想快速搭起一套可复用的T恤设计模块的开发者。系统的核心价值在于把最难的画布交互部分封装好了你拿到手之后改改接口就能嵌入自己的项目。2. 技术选型与项目初始化先看清整体架构再动手2.1 技术选型为什么是Web端优先而不是小程序端这套系统在技术栈的选择上走的是“快速落地”路线。前端采用Vue全家桶配合Canvas渲染方案后端为轻量级接口服务数据库用MySQL承接订单和SKU数据。选这套组合的原因很直接T恤设计交互的核心场景在电脑端——用户需要高精度地拖拽素材、微调文字、切换图案鼠标的精细操作远胜触屏。同时Canvas在Web端的生态最成熟对图片合成、像素处理的支持也最完善。如果你打算同时支持小程序端这套系统的前端绘制逻辑无法直接复用你需要用小程序的原生Canvas重新实现一遍画布部分而后端的订单接口和SKU逻辑是通用的。实际项目里不少团队会先上线Web端验证设计交互再考虑小程序端这套源码的结构正好匹配这个节奏。2.2 环境准备与项目初始化三个步骤跑起本地环境拿到源码包解压之后项目结构分三块前端目录、后端目录、数据库脚本。初始化顺序建议“先数据库后后端再前端”因为前端接口需要后端先能访问。先看数据库初始化脚本在MySQL中执行CREATE DATABASE tshirt_diy DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; USE tshirt_diy; SOURCE /你的解压路径/sql/init.sql;这里有个细节utf8mb4字符集是必须的。素材库里有中文字体配置和可能的Emoji图案如果用了utf8中文能正常存一旦用户上传的图片文件名带生僻字或特殊符号就会写入失败。我见过不止一个项目在字符集上翻车表现是订单提交时有概率报Incorrect string value错误。初始化完成后按顺序启动后端服务和前端开发服务器# 后端服务默认监听3000端口 cd server npm install node app.js# 前端开发服务器默认监听8080端口需要配置跨域代理 cd client npm install npm run dev两个终端分别跑起来浏览器打开前端地址就能看到设计器页面。注意前端目录里的vue.config.js有代理配置把/api请求转发到后端3000端口如果你改了后端端口这里要同步修改。这套结构是本地开发和线上部署通用的后端上线时建议用PM2或类似进程守护工具跑Node服务避免进程意外退出。2.3 目录结构与会话级画布存档搞清楚每个目录的职责解压后你会看到一套按职责划分的目录结构理解它的分层方式比直接改代码更重要client/src前端源码。其中views/designer是核心设计器页面components/canvas下封装了画布操作组件store/里有Vuex状态管理专门存当前设计会话。client/src/utils素材处理工具和价格计算函数。server/routes后端接口路由包括订单创建、素材列表、SKU查询。server/utils图片合成服务负责把用户设计好的画布导出成高清PNG。会话级画布存档是我比较认可的一个设计设计器中的每一次操作拖拽、换色、素材增删都会写入Vuex状态组件切时不会丢失刷新页面时从本地缓存恢复。它把“用户设计到一半的场景跑通了——如果用户刷新就丢设计稿等于逼用户一次性完成转化率会很难看。这套源码在client/src/store/modules/design.js里实现了设计数据的序列化和反序列化本地存储的键值字段封装得也比较清晰你可以直接复用。3. 核心功能模块的实现逻辑从画布交互到订单提交3.1 画布交互拖拽、缩放、旋转与图层管理的实现方式设计器页面的核心交互就是素材元素的操作。用户拖拽一个图形到T恤轮廓上除了要让它出现还要能选中、移动、缩放、旋转、调整层级顺序。这套源码没有用现成的Canvas框架而是自己实现了基于坐标系的矩阵变换逻辑。看一个关键代码片段它负责画布元素的状态管理// client/src/store/modules/design.js const state { elements: [], // 画布上的元素数组 selectedElementId: null, // 当前选中的元素ID history: [] // 操作历史用于撤销重做 }; const mutations { UPDATE_ELEMENT(state, payload) { const index state.elements.findIndex(el el.id payload.id); if (index ! -1) { state.elements[index] { ...state.elements[index], ...payload.updates }; } }, ADD_HISTORY(state) { // 快照当前元素数组入栈最多保留30步 if (state.history.length 30) { state.history.shift(); } state.history.push(JSON.parse(JSON.stringify(state.elements))); } };这个实现的核心思路是所有画布元素的数据都收敛到Vuex的elements数组里Canvas渲染层只是这个数组的“投影”。每次拖拽触发的是UPDATE_ELEMENT而不是直接改DOM或Canvas坐标这样组件间的状态同步就简单了。历史记录用数组快照限制30步是实际的取舍——每个快照包含元素坐标、尺寸、旋转角、图层ID存的太多会导致性能下降。操作Canvas渲染时坐标变换是这个模块的难点。比如拖动图片时有一个基础公式新位置 旧位置 鼠标移动的距离。但如果元素处于缩放或旋转状态坐标计算就要叠加变换矩阵。源码里把旋转角度和缩放比例单独存储计算元素实际边界时用ctx.translate和ctx.rotate还原变换状态这块建议重点看components/canvas/CanvasStage.vue里的getElementBounds方法理解透了你就能自行扩展素材倾斜、翻转等操作。3.2 参数定制链路颜色、尺码、面料与SKU联动T恤定制不能只是图案设计还要把商品参数贯穿起来。这件T恤提供多种颜色和尺码面料选项影响价格用户选错尺码时还需要有友好提示。源码中的SKU联动逻辑是前后端分离实现的——前端拉取商品可变规格列表后端校验所选组合是否有效。看后端的SKU查询接口实现// server/routes/product.js const express require(express); const router express.Router(); router.get(/skus/:productId, async (req, res) { const { productId } req.params; const { color, size, fabric } req.query; // 组合三个维度查询有效的SKU记录 const sql SELECT sku_id, price_extra, stock FROM skus WHERE product_id ? AND color ? AND size ? AND fabric ? ; const results await db.query(sql, [productId, color, size, fabric]); if (results.length 0) { return res.status(404).json({ code: SKU_NOT_FOUND, message: 该组合暂时缺货请尝试其他搭配 }); } res.json({ code: 0, data: { skuId: results[0].sku_id, priceExtra: results[0].price_extra, stock: results[0].stock } }); });这个接口的关键在于“组合查询”和“库存校验”合二为一了。前端拿到price_extra后实时更新价格拿到stock后控制下单按钮的可点击状态。注意接口中没有一个“查询所有SKU”的逻辑。前端拿到SKU数据后的状态逻辑也很关键在store/modules/sku.js中维护当前已选参数const state { selectedOptions: { color: null, size: null, fabric: null } }; const getters { currentSkuValid: (state, getters, rootState) { return state.selectedOptions.color state.selectedOptions.size state.selectedOptions.fabric; }, currentSkuId: (state, getters, rootState) { return getters.skuIdMap[${state.selectedOptions.color}_${state.selectedOptions.size}_${state.selectedOptions.fabric}]; } };skuIdMap是前端在页面加载时预取的所有SKU映射表这样切换选项时不需要每次都请求后端页面响应更快。但这也是容易出错的点如果你在后端修改了SKU组合常见做法是用productId维度全量刷新映射表避免请求数据与服务端不一致。3.3 加价规则与价格计算梯度计价与实时刷新T恤定制的价格逻辑通常是“基础价 参数加价 设计加价”。设计加价的规则比较复杂允许用户免费添加1个设计图案第二个图案起每个加收固定费用。这个梯度计价的实现在前端utils/price.js中直接给出关键代码// client/src/utils/price.js export function calcPrice(basePrice, skuExtra, elementCount) { let designExtra 0; // 第一个图案免费第二个起每个加收15元 if (elementCount 1) { designExtra (elementCount - 1) * 15; } // 设计素材数量超过5个超过部分每个加收10元 if (elementCount 5) { designExtra (elementCount - 5) * 10; } return basePrice skuExtra designExtra; }这个计价方式适合用来理解系统的设计思路——它不是固定价格而是允许你通过配置调整加价阈值和金额。实际业务中你可能要做“免费图案数可配置”“不同素材类型不同加价”等调整改动核心就是这个函数。要注意的是这种梯度计价是前端展示用的下单时后端务必基于订单明细重算一遍价格不能直接信任前端提交的总价。4. 常见问题与排查四个必踩的坑4.1 图片跨域导致的Canvas污染现象用户上传一张网络图片作为T恤图案设计器里显示正常但最终导出图片时Canvas变成空白控制台报Uncaught DOMException: Failed to execute toDataURL on HTMLCanvasElement: Tainted canvases。原因Canvas被跨域图片“污染”了。浏览器出于安全策略一旦Canvas绘制过不属于当前域名下的图片资源toDataURL()和toBlob()就会被禁用。上传到本地或用内网地址访问时正常是因为同源。解决为网络图片统一走服务端代理下载或者使用服务端接口。常见做法是在后端做一个图片转发接口前端把图片URL传给后端后端以流的方式返回图片二进制数据这样前端拿到的图片资源就是同域的了。如果你只想快速排查最简单的验证方法是把所有测试图片放在和前端域名同域的目录下操作就不报错了。4.2 移动端触摸事件的坐标偏移现象用手机浏览器打开设计器拖动素材时元素跑偏触摸点对应的不是素材本体而是某个偏移的位置。原因移动端触摸事件和鼠标事件的对象结构不同。鼠标事件里用的是clientX/clientY触摸事件里要用touches[0].clientX/touches[0].clientY。如果代码里只绑定mousedown/mousemove/mouseup在触屏设备上会异常如果绑定了touchstart/touchmove/touchend却没适配坐标就会出现偏移。解决不要同时监听鼠标和触摸事件而是做统一的指针事件封装——判断事件类型取对应的坐标字段。这套源码中的CanvasStage.vue用的是pointerdown/pointermove/pointerup事件天然兼容鼠标和触摸。如果你拿到的版本还是老的鼠标事件写法建议升级成指针事件。4.3 订单详情里的缩略图变成空白现象用户下单成功后订单列表里的缩略图显示正常但订单详情页的缩略图偶尔空白。原因订单缩略图是生成图片时的异步环节。用户提交订单后服务端异步执行图片合成任务。列表页读取的是缓存详情页读取的是服务端最新生成结果如果合成任务还没完成就返回了详情页数据缩略图字段就是空的。解决不要让异步环节阻塞到下单返回链路中。把图片合成任务和下单步骤解耦——下单时记录设计数据JSON图片合成通过队列异步处理生成完成回写数据库前端轮询或主动刷新图片地址。这套源码在后端有一个定时扫描待处理订单并生成图片的脚本所以你拿到手后需要确认这个脚本在线上是“启用”状态。很多部署后订单图片空白的案例排查到最后都是这个脚本被停了或者执行报错。4.4 高并发下单时SKU库存扣减超卖现象促销场景下某热门尺码的T恤实际卖出数量超出库存数量。原因扣减库存使用了一条“先查后改”的流程缺乏数据库层面的原子性和事务隔离保障。// 错误示例先查库存再扣减 const stock await db.query(SELECT stock FROM skus WHERE sku_id ?, [skuId]); if (stock 0) { await db.query(UPDATE skus SET stock stock - 1 WHERE sku_id ?, [skuId]); }两个请求同时查到库存为1时两者都判断可扣减都执行了UPDATE最终库存变成-1。解决把“检查扣减”合并成一个原子操作且必须影响行数大于等于1才判定为成功// 正确做法一条SQL原子扣减 const result await db.query( UPDATE skus SET stock stock - 1 WHERE sku_id ? AND stock 0 , [skuId]); if (result.affectedRows 0) { // 扣减失败说明库存不足中止下单 return res.status(400).json({ code: OUT_OF_STOCK, message: 库存不足 }); }这段代码的思路是让数据库来保证“库存大于0才允许扣减”而不是在应用层用SELECT判断这样并发下每一笔扣减都在数据库层面收到约束。实际项目中如果SKU数量特别大、并发特别集中还可以在上游加分布式锁或限流但先把这条SQL改成原子扣减是最基本的兜底。5. 上线前要做的验证与优化把Demo推成能用的系统5.1 素材防滥用与版权审核机制做定制系统绕不开版权问题。这套源码把“用户上传图片”和“平台素材库”分成两条链路。平台素材库中的素材需要你预置要确保这些素材是已获得授权的用户上传的素材则需要在提交订单时增加一个协议确认环节声明用户对素材拥有使用权。上线前把这两点确认清楚比任何安全补丁都重要。5.2 图片输出的三种尺寸配置与合成效率用户设计完成后系统要导出一张高清图用于印刷同时生成一张缩略图用于订单详情外还有一张供前端预览。这三种尺寸的需求不同——印刷图需要至少300dpi建议宽度不低于2000像素订单详情图800px左右列表缩略图300px。后端合成脚本中建议做三个配置项对应不同输出路径。由于合成是I/O密集型任务建议参考固定数量的worker并发执行避免占用过多CPU资源导致与后端主进程抢占资源。5.3 设计图与订单数据的强关联别丢数据我在一个模拟项目里吃过亏——产品演示时一切正常但一上线后台就能看到不少订单创建了而设计图文件却是零字节。后来排查发现问题出在订单表和设计图文件是“引用关系”一旦用户刷新页面或网络抖动导致上传中断文件没存上但订单照常创建后续图片是空的。处理方式其实很简单把“订单创建”和“图片上传保存”做成一个事务流程图片文件上传成功才算订单创建成功。从那以后我每次要做一个带定制设计的订单系统都会强制走一遍这个检查设计图文件是否和订单有强一致的落下顺序异步生成图片的脚本是否在线上出现异常时有人会立刻收到告警如果这两点没验证再好看的前端交互我都觉得心里没底。这个系统的核心价值不在界面有多花哨而在它的业务逻辑覆盖度——从设计器交互、SKU组合、价格计算、订单落地到生产端需要的图片导出每个环节都有落地的实现参考。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑