首页 > 解决方案 > 如何使用fabric.Textbox类覆盖在fabric js中制作自定义类?

问题描述

  1. 我正在使用 FabricJS 版本:3.6.3
  2. 我想创建一个名为:Button 的新 FabricJS 类
  3. 所以我扩展了一个Textbox从fabric js调用的类,它会在后面一个看起来像一个按钮的类。RectangleText
  4. 但问题是,我不能设置heightButton因为对象height中不允许Texbox
  5. 我想设置HeightWidth反对ButtonWidth由于 . 正在正常工作Textbox。如果宽度保持小于文本宽度,它也会扭曲文本,并且可以通过双击它进行编辑。但唯一的问题是不能设置Heightobject
  6. 应该是Text vertically center什么时候Height增加。

简而言之,我想使用对象自定义在 Fabric js 中实现这种功能。

预期输出:

在此处输入图像描述

实际输出:

在此处输入图像描述

这是我创建按钮的代码:

// fabric js custom button class
(function (fabric) {
  "use strict";

  // var fabric = global.fabric || (global.fabric = {});

  fabric.Button = fabric.util.createClass(fabric.Textbox, {
    type: "button",
    stateProperties: fabric.Object.prototype.stateProperties.concat(
      "buttonRx",
      "buttonRy",
      "buttonFill",
      "buttonPadding",
      "buttonStrokeColor",
      "buttonStrokeWidth"
    ),
    buttonRx: 0,
    buttonRy: 0,
    buttonFill: "#ffffff00",
    buttonPadding: 0,
    buttonHeight: 0,
    buttonWidth: 0,
    textAlign: "center",
    buttonStrokeColor: "#000000",
    buttonStrokeWidth: 0,
    _dimensionAffectingProps: fabric.Text.prototype._dimensionAffectingProps.concat(
      "width",
      "fontSize"
    ),
    cacheProperties: fabric.Object.prototype.cacheProperties.concat(
      "buttonRx",
      "buttonRy",
      "buttonFill",
      "buttonPadding",
      "buttonStrokeColor",
      "buttonStrokeWidth"
    ),
    initialize: function (text, options) {
      this.text = text;
      this.callSuper("initialize", text, options);
      /* this.on("scaling", function () {
        console.log('scaling', this.getScaledHeight());
        
        this.set({
          height: this.getScaledHeight(),
          scaleY: 1,
        });
      }); */

      this._initRxRy();
    },

    _initRxRy: function () {
      if (this.buttonRx && !this.buttonRy) {
        this.buttonRy = this.buttonRx;
      } else if (this.buttonRy && !this.buttonRx) {
        this.buttonRx = this.buttonRy;
      }
    },
    /* _setCenter(){

    }, */
    _render: function (ctx) {
      // 1x1 case (used in spray brush) optimization was removed because
      // with caching and higher zoom level this makes more damage than help
      // this.width = this.width * this.scaleX;
      // this.height = this.height * this.scaleY;
      // (this.scaleX = 1), (this.scaleY = 1);
      var rx = this.buttonRx ? Math.min(this.buttonRx, this.width / 2) : 0,
        ry = this.buttonRy ? Math.min(this.buttonRy, this.height / 2) : 0,
        w = this.width + this.buttonPadding,
        h = this.height + this.buttonPadding,
        x = -this.width / 2 - this.buttonPadding / 2,
        y = -this.height / 2 - this.buttonPadding / 2,
        isRounded = rx !== 0 || ry !== 0,
        /* "magic number" for bezier approximations of arcs (http://itc.ktu.lt/itc354/Riskus354.pdf) */
        k = 1 - 0.5522847498;
      ctx.beginPath();

      ctx.moveTo(x + rx, y);

      ctx.lineTo(x + w - rx, y);
      isRounded &&
        ctx.bezierCurveTo(x + w - k * rx, y, x + w, y + k * ry, x + w, y + ry);

      ctx.lineTo(x + w, y + h - ry);
      isRounded &&
        ctx.bezierCurveTo(
          x + w,
          y + h - k * ry,
          x + w - k * rx,
          y + h,
          x + w - rx,
          y + h
        );

      ctx.lineTo(x + rx, y + h);
      isRounded &&
        ctx.bezierCurveTo(x + k * rx, y + h, x, y + h - k * ry, x, y + h - ry);

      ctx.lineTo(x, y + ry);
      isRounded && ctx.bezierCurveTo(x, y + k * ry, x + k * rx, y, x + rx, y);

      ctx.closePath();
      ctx.save();
      if (this.buttonFill) {
        ctx.fillStyle = this.buttonFill;
        if (this.fillRule === "evenodd") {
          ctx.fill("evenodd");
        } else {
          ctx.fill();
        }
      }
      if (this.buttonStrokeWidth > 0) {
        if (this.strokeUniform) {
          ctx.scale(1 / this.scaleX, 1 / this.scaleY);
        }
        if (this.shadow && !this.shadow.affectStroke) {
          this._removeShadow(ctx);
        }
        if (this.buttonStrokeColor) {
          ctx.lineWidth = this.buttonStrokeWidth;
          ctx.strokeStyle = this.buttonStrokeColor;
          ctx.stroke();
        } else {
          ctx.lineWidth = this.buttonStrokeWidth;
          ctx.stroke();
        }
      }
      ctx.restore();

      this.clearContextTop();
      this._clearCache();
      this.height = this.calcTextHeight();
      this.saveState({ propertySet: "_dimensionAffectingProps" });
      //   this._renderPaintInOrder(ctx);

      this._setTextStyles(ctx);
      this._renderTextLinesBackground(ctx);
      this._renderTextDecoration(ctx, "underline");
      this._renderText(ctx);
      this._renderTextDecoration(ctx, "overline");
      this._renderTextDecoration(ctx, "linethrough");
      this.initDimensions();
      // this.callSuper('render', ctx);
    },
    toObject: function (propertiesToInclude) {
      return this.callSuper(
        "toObject",
        [
          "buttonRx",
          "buttonRy",
          "buttonFill",
          "buttonPadding",
          "buttonStrokeColor",
          "buttonStrokeWidth",
          "objectCaching",
        ].concat(propertiesToInclude)
      );
    },
  });

  fabric.Button.fromObject = function (object, callback) {
    return fabric.Object._fromObject("Button", object, callback, "text");
  };
})(fabric);

// fabric js class finish here


var canvas = [];
var cotainer = document.getElementById("canvas-container");
for (let i = 0; i < 1; i++) {
  var width = 500,
    height = 500;
  var canvasEl = document.createElement("canvas");
  canvasEl.id = "canvas-" + i;
  cotainer.append(canvasEl);
  var fabCanvas = new fabric.Canvas(canvasEl, {});
  fabCanvas.setHeight(height);
  fabCanvas.setWidth(width);
  canvas.push(fabCanvas);
}

canvas.forEach((c) => {
  var button = new fabric.Button("Click Me", {
    text: "Click Me",
    buttonStrokeColor: "#f00",
    buttonStrokeWidth: 2,
    width: 110,
    fill: "#f00",
    fontSize: 50,
    width: 400,
    buttonFill: "#42A5F5",
    buttonRx: 15,
    buttonRy: 15,
    objectCaching: false,
    fontFamily: "verdana",
  });
  c.add(button);
  c.renderAll();
});
canvas{
border: 1px solid black
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.2/fabric.js"></script>
<div id="canvas-container">
</div>

标签: buttontextboxfabricjs

解决方案


解决方案是在缩放按钮对象时将按钮文本的 scaleX 和 scaleY 设置为 1,并将文本的字体大小设置为等于其比例。


推荐阅读