必须用 layer.open() 替代 layui.upload 的默认预览,手动构造含图片和旋转按钮的 HTML;旋转需通过修改 img 的 transform 属性实现,并设置 transform-origin 为 center center,配合角度变量动态更新。
不能直接在 layui.upload 的预览弹窗里加按钮——它不提供 content dom 的可编辑入口,必须绕过默认 preview 逻辑,自己接管预览层。
layui.upload 的 obj.preview() 只负责生成 base64 并插入到你指定的容器中,但它不暴露预览层 DOM 结构,也没法往里面塞按钮。真正能自定义 UI 的,是 layer.open()。
choose 回调里拿到 result(base64)后,不要用它直接塞进某个 div,而是调用 layer.open() 手动构造内容content 参数写成包含 <img> + 自定义按钮的 HTML 字符串,比如:`<div class="preview-wrap"><img src="${result}" id="preview-img"><div class="toolbar"><button id="rotate-left">↺</button><button id="rotate-right">↻</button></div></div>`
success 回调里绑定按钮事件,此时 DOM 已挂载,document.getElementById('rotate-left') 才能取到点击旋转按钮时,不能重新赋值 src(那会触发重加载、丢失当前缩放状态),而应修改 style.transform。Layui 预览层里的 <img> 默认没有设置 transform-origin,会导致旋转中心偏移。
#preview-img 加上 style="transform-origin: center center;"
let rotateDeg = 0)记录当前角度,每次点击 ±90°,然后更新:img.style.transform = `rotate(${rotateDeg}deg)`
scale 和 rotate 合并在同一个 transform 值里,例如:transform: rotate(90deg) scale(1.5)
很多人混淆了「单图上传前预览」和「多图相册预览」。前者用 layer.open() + obj.preview() 搭配完全够用;后者若要用 layer.photos() 再加按钮,则必须等它渲染完成,在 success 回调里用类名定位(如 .layui-layer-photos .layui-layer-content),但风险高——Layui 内部结构可能随版本微调,且 layer.photos() 本身不支持传入自定义 toolbar。
layer.open(),别碰 layer.photos()
position: absolute; top: 10px; right: 10px; 这类定位,避免被图片尺寸撑乱布局min-width: 40px; min-height: 40px;,否则 iOS 上点不中真正难的不是加按钮,而是让旋转后图片仍能正常缩放、拖拽、居中——这些状态要和 transform 同步维护。一旦开始混用 CSS transform,就再也不能靠简单改 width/height 控制缩放了。