You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复FabricJS缩放多边形的裁剪偏移问题

Fixing FabricJS Clipping Offset When Scaling Clip Polygon

Hey there! I see the issue you're facing—when scaling your clip polygon, the clipping region shifts incorrectly. Let's break down why this is happening and fix it.

The Root Cause

Your original clipRegion function was manually calculating point positions without properly accounting for the full transformation matrix of the clip polygon, especially when it's scaled. The manual subtraction and scaling math didn't account for how FabricJS applies origin-based transformations to objects, leading to the offset.

The Fixed Solution

Here's the revised code that correctly handles transformations for both the clipped rectangle and the clip polygon:

var canvas = new fabric.Canvas('c');
var rect1 = new fabric.Rect({
 left: 0,
 top: 0,
 width: 900,
 height: 900,
 fill: 'blue',
 selectable: false,
 clipTo: clipRegion,
 scaleX: 1.5,
 scaleY: 1.5
});
var clipPoly = new fabric.Polygon([
 { x: 180, y: 10 },
 { x: 300, y: 50 },
 { x: 300, y: 180 },
 { x: 180, y: 220 }
], {
 originX: 'left',
 originY: 'top',
 left: 180,
 top: 10,
 fill: 'transparent',
 strokeWidth: 1,
 stroke: "red",
 scaleX: 1.3,
 scaleY: 1.3
});
canvas.add(rect1, clipPoly);

function clipRegion(ctx) {
  const clipObj = clipPoly;
  ctx.save();

  // Step 1: Shift context to match rect1's local coordinate system
  // Reverse rect1's transformations to work in its native space
  ctx.translate(rect1.left, rect1.top);
  ctx.rotate((rect1.angle * Math.PI) / 180);
  ctx.scale(rect1.scaleX, rect1.scaleY);
  ctx.translate(-rect1.width / 2, -rect1.height / 2);

  // Step 2: Convert clip polygon's raw points to canvas-level coordinates
  // This applies all of the polygon's transformations (scale, position, etc.)
  const canvasPoints = clipObj.points.map(point => {
    return fabric.util.transformPoint(point, clipObj.calcTransformMatrix());
  });

  // Step 3: Convert canvas coordinates back to rect1's local space
  // Using rect1's inverse transform matrix ensures perfect alignment
  const rectInverseMatrix = rect1.calcTransformMatrix().invert();
  const localPoints = canvasPoints.map(point => {
    return fabric.util.transformPoint(point, rectInverseMatrix);
  });

  // Step 4: Draw the clipping path
  ctx.beginPath();
  ctx.moveTo(localPoints[0].x, localPoints[0].y);
  localPoints.forEach(point => {
    ctx.lineTo(point.x, point.y);
  });
  ctx.closePath();

  ctx.restore();
}

Key Changes Explained

  • Context Alignment: We first adjust the canvas context to match rect1's local coordinate system. This reverses the rectangle's position, rotation, and scaling so we can draw the clip path in the same space as the rectangle itself.
  • Built-in Transformation Tools: Instead of manual math, we use fabric.util.transformPoint to apply the clip polygon's full transformation matrix to its raw points. This automatically accounts for scaling, translation, rotation, and origin settings—something your original code missed.
  • Inverse Matrix Conversion: We convert the clip polygon's canvas coordinates back to rect1's local space using the inverse of the rectangle's transform matrix. This guarantees the clip path stays perfectly aligned, no matter how either object is transformed.

This approach relies on FabricJS's native transformation utilities, eliminating errors from manual calculations. Now your clipping will stay accurate even when you scale, rotate, or move the clip polygon.

内容的提问来源于stack exchange,提问作者Internalsi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 06:54:50