diff --git a/src/canvas/canvas-object-factory.ts b/src/canvas/canvas-object-factory.ts index 742d7e8bf..1c92a33e8 100644 --- a/src/canvas/canvas-object-factory.ts +++ b/src/canvas/canvas-object-factory.ts @@ -320,7 +320,14 @@ export function createFabricObject( if (pw > 0 && ph > 0 && obj.width && obj.height) { // Uniform scale — preserve aspect ratio so icons don't get squished const uniformScale = Math.min(pw / obj.width, ph / obj.height) - obj.set({ scaleX: uniformScale, scaleY: uniformScale }) + if (node.iconId) { + // For icon nodes: expand the Fabric bounding box to pw×ph so the selection + // handles always form a perfect square. The path content is naturally centered + // by Fabric's pathOffset (center of path's bbox). + obj.set({ width: pw / uniformScale, height: ph / uniformScale, scaleX: uniformScale, scaleY: uniformScale }) + } else { + obj.set({ scaleX: uniformScale, scaleY: uniformScale }) + } } break } diff --git a/src/canvas/canvas-object-sync.ts b/src/canvas/canvas-object-sync.ts index 565f16a74..8eccc33f1 100644 --- a/src/canvas/canvas-object-sync.ts +++ b/src/canvas/canvas-object-sync.ts @@ -187,7 +187,13 @@ export function syncFabricObject( if (node.type === 'path') { // Uniform scale — preserve aspect ratio so icons don't get squished const uniformScale = Math.min(w / nw, h / nh) - obj.set({ width: nw, height: nh, scaleX: uniformScale, scaleY: uniformScale }) + if (node.iconId) { + // Expand bounding box to w×h so selection handles form a perfect square. + // Path content is centered automatically by Fabric's pathOffset. + obj.set({ width: w / uniformScale, height: h / uniformScale, scaleX: uniformScale, scaleY: uniformScale }) + } else { + obj.set({ width: nw, height: nh, scaleX: uniformScale, scaleY: uniformScale }) + } } else { obj.set({ width: nw, height: nh, scaleX: w / nw, scaleY: h / nh }) }