活动海报、节日贺卡,底图上要叠几张装饰。点下面素材贴上去,拖到合适位置,两指捏合放大缩小,转一下角度。不需要的点右上角 X 拿掉。
入口是 index.html。样式在 css/diy.css,点选、删除、置顶在 js/diy.js。手势封装在 js/myTouchImg.js,底层是 js/touch.min.js。脚本先引 jQuery,再引 resize.js,最后才是 touch、myTouchImg.js、diy.js。jQuery 掉到后面,$ 会挂;touch 掉到 myTouchImg.js 后面,touch 是空的。
贴纸组合用到哪些文件

html 里按这个顺序引:

页面就这三层:#box 包住整页,#img 是底图,.ioc-main-box 叠在底图上专门放贴纸,.ioc-list 是下面一排素材。维护的时候把入口指到 index.html 就行。
页面骨架

.ioc 和 .set-close 加上 cursor: pointer。
画布和素材列表如何布局
#box 相对定位,高度 5rem。resize.js 按屏宽给 html 写字号:宽度最大按 750 算,除以 7.5。说白了,375 宽的手机上 1rem 大约 50 像素,画布大约 250 像素高;到 750 宽就是 500 像素高,再宽也不再撑。转屏会重算一次。
.ioc-main-box 绝对铺在底图上,overflow: hidden,贴纸拖出画布的部分裁掉。z-index: 10 保证贴纸盖住底图,不要被底图挡住点不到。
素材 .ioc 宽 100 像素,左右各留 20 像素。贴纸 .set-box 绝对定位,本例初始写在 left: 200px; top: 300px,方便立刻看见贴上去了;业务里按设计改。关闭钮叠在贴纸左上角,宽 0.3rem。

底图 #img 和画布同高,路径换成业务图即可。
如何把贴纸放到画布上
点 .ioc,把这块素材的 src 拼进一个 .set-box,丢进 .ioc-main-box。里面一张 .set-img,一张 .set-close。draggable="false" 拦住浏览器自己的拖图虚影,不然跟手势抢。
拼完立刻 myTouchjs($(".set-box").last())。只绑刚贴上去的那一块,老贴纸不要重新绑一遍,否则拖一次会跳两下。这坑我见过不止一次。

关掉就删掉父级 .set-box。点中某张要盖住别的,给自己 z-index: 1,兄弟设成 0。事件挂在 body 上委托,贴纸是后插进去的,写死 .click() 新节点点不到。

置顶同时听 mousedown 和 touchstart,电脑和手机都能把点中的那张拎上来。
贴纸如何拖动、缩放和旋转
myTouchjs 给传入的 jQuery 对象绑三件事:单指拖、两指捏合、旋转。每次变化拼一条 transform:translate 位移,scale 倍数,rotate 角度,写回节点。-webkit-transform 一并写上,旧 WebKit 才认。
拖的时候 ev.x、ev.y 是这一次手指相对起点的偏移,要加在上一次停住的 x、y 上。松手(dragend)或系统打断(touchcancel)时,把当前 setX、setY 存回去,下一趟才接着走,不会弹回原处。
捏合用 ev.scale。scaleVal 是当前倍数,initialScale 是这一轮开始时的倍数。公式是 当前 = 开始时的倍数 + (ev.scale - 1)。两指放开走 pinchend,把这一轮的倍数记成下一轮的起点。我第一次看也卡了一下:直接拿 ev.scale 当最终倍数,第二轮捏合会从 1 再起跳。
旋转累加 ev.rotation。手指结束那一帧 fingerStatus === "end",把角度固化进 angle,下一圈接着转,不会每次从 0 起。

电脑上 touch.min.js 会把鼠标映射成这套事件,单指拖能用。捏合、旋转要两指,用手机或开了触摸的屏幕才好试。
如何对接到真实项目中
底图和素材不要写死。接口返回底图地址、贴纸列表,再填进 #img 和 .ioc-list。jQuery 这套建议用 Layui 做提示,具体按实际项目来定。接口失败走 layer.msg,不要 alert。
/api/sticker/detail 的路径和字段换成项目约定。下面这份覆盖 diy.js,页面结构仍用前面的 html。

#box 带上 data-id。没有接口就把 #img 和 .ioc 的 src 写成项目里的图路径。画布高度、贴纸初始坐标按设计改;touch.min.js 整文件带着走,不要只拷 myTouchImg.js。