fix(canvas): ensure icon selection box is always square with centered content

For icon nodes (PathNode with iconId), expand Fabric's logical bounding box to
the declared w×h so selection handles always form a perfect square, while the
path content remains centered via Fabric's natural pathOffset.
This commit is contained in:
Fini 2026-02-24 00:50:23 +08:00
parent 0c456fe4d2
commit 312ffd7cb4
2 changed files with 15 additions and 2 deletions

View file

@ -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
}

View file

@ -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 })
}