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

如何使用Fabric.js绘制可调节的精确直角(替代矩形方案)

在Fabric.js中绘制可调节的精确直角(单元素实现)

不用拼接两个矩形,直接基于fabric.Path实现单个可调节的直角图形,既保证形状精确,又支持参数化调整。

核心实现思路

通过自定义fabric.Path子类,用路径指令定义L形直角形状,将直角的边长、厚度作为可修改属性,同时支持添加自定义控制点实现可视化调节。

代码实现

// 自定义直角图形类
class RightAngle extends fabric.Path {
  constructor(options) {
    const { length1 = 100, length2 = 100, thickness = 20, ...rest } = options;
    
    // 生成L形填充路径
    const filledPath = `M 0,0 
                        L ${length1},0 
                        L ${length1},${thickness} 
                        L ${length1 - thickness},${thickness} 
                        L ${length1 - thickness},${length2} 
                        L 0,${length2} 
                        L 0,${length2 - thickness} 
                        L ${thickness},${length2 - thickness} 
                        L ${thickness},0 
                        Z`;

    super(filledPath, {
      ...rest,
      length1,
      length2,
      thickness,
      originX: 'center',
      originY: 'center',
    });

    // 替换默认控制点,添加自定义调节点
    this.setControlsVisibility({
      mt: false, mb: false, ml: false, mr: false,
      mtr: true
    });

    this.controlPoints = {
      // 调节水平边长的控制点
      endHorizontal: new fabric.Control({
        position: { x: 1, y: 0 },
        offsetY: thickness / 2,
        actionHandler: (_, __, x) => {
          const newLength = Math.max(thickness, x - this.left + this.width / 2);
          this.setLength1(newLength);
          return true;
        }
      }),
      // 调节垂直边长的控制点
      endVertical: new fabric.Control({
        position: { x: 0, y: 1 },
        offsetX: thickness / 2,
        actionHandler: (_, __, _, y) => {
          const newLength = Math.max(thickness, y - this.top + this.height / 2);
          this.setLength2(newLength);
          return true;
        }
      })
    };
    this.controls = { ...this.controls, ...this.controlPoints };
  }

  // 更新水平边长
  setLength1(newLength) {
    this.length1 = newLength;
    this._updatePath();
  }

  // 更新垂直边长
  setLength2(newLength) {
    this.length2 = newLength;
    this._updatePath();
  }

  // 更新边厚度
  setThickness(newThickness) {
    this.thickness = newThickness;
    this._updatePath();
    // 更新控制点偏移
    this.controlPoints.endHorizontal.offsetY = newThickness / 2;
    this.controlPoints.endVertical.offsetX = newThickness / 2;
  }

  // 重新生成路径并渲染
  _updatePath() {
    const { length1, length2, thickness } = this;
    const filledPath = `M 0,0 
                        L ${length1},0 
                        L ${length1},${thickness} 
                        L ${length1 - thickness},${thickness} 
                        L ${length1 - thickness},${length2} 
                        L 0,${length2} 
                        L 0,${length2 - thickness} 
                        L ${thickness},${length2 - thickness} 
                        L ${thickness},0 
                        Z`;
    this.set('path', fabric.Path.fromPath(filledPath).path);
    this.canvas && this.canvas.renderAll();
  }
}

// 添加直角到画布的方法
addRightAngle = () => {
  const rightAngle = new RightAngle({
    left: this.canvas.width / 2,
    top: this.canvas.height / 2,
    fill: '#ffa726',
    length1: 100,
    length2: 100,
    thickness: 20,
    centeredRotation: true,
    strokeWidth: 0
  });
  this.canvas.add(rightAngle);
}

使用说明

  1. 参数调节:直接调用setLength1、setLength2、setThickness方法可修改直角的尺寸,调用后画布自动重绘。
  2. 可视化调节:图形自带两个自定义控制点,拖动可分别调节水平和垂直方向的边长,厚度可通过代码修改。
  3. 旋转与定位:保留了centeredRotation和原点居中的设置,支持和普通矩形一样的旋转、拖拽操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 18:16:03