Textbox
from fabric js, which will Draw a Rectangle
behind Text
and it looking like a button.height
to that Button
because height
is not allow in Texbox
object.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
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>
The solution will be to set the scaleX and scaleY of the button text to 1 when you scale the Button Object and also set the font size of the text equal to its scale.