Fabric.js组缩放时固定部分对象尺寸并同步位置的实现方法
Solution for Keeping a Child Object Fixed-Sized in a Scaling Fabric.js Group
Got it, let's fix this issue where your circle gets stretched into an oval when scaling the group. The core problem is that all child objects in a Fabric.js group inherit the group's scale by default—we need to override that behavior for your linkBtn and keep its position tied to the rectangle's top center.
Here's the modified code with explanations:
var r = 15; var rect = new fabric.Rect({ left: 50, top: 50, fill: 'blue', width: 100, height: 100 }); var linkBtn = new fabric.Circle({ left: 50 + rect.width / 2 - r, top: 50 - r, strokeWidth: 1, radius: r, fill: '#fff', stroke: '#666' }); var g = new fabric.Group([rect, linkBtn]); g.hasRotatingPoint = false; // Listen for scaling changes on the group g.on('scaling', function() { // Cancel out the group's scale to keep the circle round and fixed-size linkBtn.scaleX = 1 / this.scaleX; linkBtn.scaleY = 1 / this.scaleY; // Recalculate the circle's position to stay at the top center of the scaled rectangle const scaledRectWidth = rect.width * this.scaleX; linkBtn.left = rect.left + scaledRectWidth / 2 - (r * this.scaleX); linkBtn.top = rect.top - (r * this.scaleY); // Update the object's coordinates to ensure proper interaction linkBtn.setCoords(); this.setCoords(); }); canvas.add(g);
How this works:
- Preventing shape distortion: By setting
linkBtn.scaleX/Yto the inverse of the group's scale, we undo the stretching effect of the group. This keeps the circle's radius fixed atrno matter how you scale the group. - Maintaining position: We calculate the scaled width of the rectangle, then adjust the circle's
leftto stay centered above it. Thetopposition is adjusted to stay exactlyrunits above the rectangle, accounting for the group's scale to avoid drifting. - Updating coordinates: Calling
setCoords()ensures Fabric.js recognizes the new position and scale, so the circle behaves correctly during interactions.
If you're using a newer version of Fabric.js, you could also explore using lockScalingX/Y on the circle, but combining that with the position update would still require the event listener to keep it aligned with the rectangle. The above approach is reliable across most Fabric.js versions.
内容的提问来源于stack exchange,提问作者Pablo Sanchez
相关产品推荐
相关产品推荐

