how to make custom class in fabric js using fabric.Textbox Class override?

孤者浪人 提交于 2020-05-09 06:05:27

问题


  1. I am using FabricJS version : 3.6.3
  2. I want to make new FabricJS class called : Button
  3. So that I have extend one class called Textbox from fabric js, which will Draw a Rectangle behind Text and it looking like a button.
  4. But Problem is that, I can't set height to that Button because height is not allow in Texbox object.
  5. I want to set Height and Width to Button object. Width is working Properly due to Textbox. it will also warp Text if width keep smaller then text width, and can be editable by double clicking on it. But only problem is that can't set Height to an object
  6. it should be Text vertically center when Height is increase.

In short I want to make this kind of functionality in fabric js using object customization.

Expected Output :

but Actual Output :

Here Is my Code That Create button :

// 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>

来源:https://stackoverflow.com/questions/61058890/how-to-make-custom-class-in-fabric-js-using-fabric-textbox-class-override

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!