问题
- I am using FabricJS version : 3.6.3
- I want to make new FabricJS class called : Button
- So that I have extend one class called
Textboxfrom fabric js, which will Draw aRectanglebehindTextand it looking like a button. - But Problem is that, I can't set
heightto thatButtonbecauseheightis not allow inTexboxobject. - I want to set
HeightandWidthtoButtonobject.Widthis working Properly due toTextbox. 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 setHeightto anobject - it should be
Text vertically centerwhenHeightis 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