FabricJS:如何同步旋转矩形与其裁剪图片(非分组方式)
FabricJS矩形与图片双向旋转同步实现方案
这是个很常见的FabricJS对象联动需求,既要实现旋转时的双向同步,又不能分组,还要保证图片基于矩形的旋转原点旋转,我来给你一步步拆解核心逻辑和具体代码实现:
核心思路拆解
要完美实现需求,得解决三个关键问题:
- 避免旋转事件的循环触发(矩形转→图片转→矩形再转的死循环)
- 统一二者的旋转原点,确保图片旋转时完全基于矩形的原点
- 计算正确的同步角度:矩形旋转时,图片角度=矩形当前角度+图片初始偏移角度;图片旋转时,矩形角度=图片当前角度-图片初始偏移角度
具体代码实现
1. 初始化画布与对象
先创建画布、红色矩形和目标图片,统一二者的旋转原点,并保存图片相对于矩形的初始角度偏移:
// 初始化FabricJS画布 const canvas = new fabric.Canvas('canvas'); // 创建红色矩形容器 const rect = new fabric.Rect({ left: 100, top: 100, width: 200, height: 200, fill: 'red', originX: 'center', originY: 'center', // 统一旋转原点为中心 hasRotatingPoint: true }); // 加载并初始化图片(替换为你的图片URL即可) fabric.Image.fromURL('https://picsum.photos/200/200', (img) => { img.set({ left: rect.left, top: rect.top, width: rect.width, height: rect.height, originX: 'center', originY: 'center', // 和矩形保持相同的旋转原点 hasRotatingPoint: true }); // 保存图片相对于矩形的初始角度差(初始状态下二者角度一致,偏移量为0) img.initialAngleOffset = img.angle - rect.angle; // 添加到画布并绑定旋转同步事件 canvas.add(rect, img); bindRotationSync(rect, img); });
2. 绑定旋转同步事件
通过一个标记位避免循环触发,实现双向同步逻辑:
function bindRotationSync(rect, img) { let isRotating = false; // 防止事件循环触发的核心标记 // 矩形旋转时同步图片角度 rect.on('rotating', () => { if (isRotating) return; isRotating = true; // 图片最终角度 = 矩形当前角度 + 初始角度偏移量 img.set('angle', rect.angle + img.initialAngleOffset); img.setCoords(); // 更新图片交互坐标,确保旋转点位置正确 canvas.renderAll(); isRotating = false; }); // 图片旋转时同步矩形角度 img.on('rotating', () => { if (isRotating) return; isRotating = true; // 矩形最终角度 = 图片当前角度 - 初始角度偏移量 rect.set('angle', img.angle - img.initialAngleOffset); rect.setCoords(); canvas.renderAll(); isRotating = false; }); }
关键细节说明
- 统一旋转原点:将
originX和originY都设为center(或你需要的自定义原点),确保图片旋转时完全贴合矩形的旋转中心,不会出现偏移错位。 - 初始角度偏移量:
initialAngleOffset用来记录图片相对于矩形的初始角度差,就算初始时图片已经有预设旋转角度,也能正确计算同步后的角度。 - 防循环标记:
isRotating标记位是核心,避免矩形旋转触发图片旋转后,图片的旋转事件又反过来触发矩形旋转,造成死循环。 - 更新交互坐标:每次修改角度后调用
setCoords(),保证对象的旋转控制点、边界框等交互元素正确更新,避免操作时出现异常。
内容的提问来源于stack exchange,提问作者Eugene Vilder
相关产品推荐
相关产品推荐

