簡體   English   中英

具有動態 fontsIze 的 FabricJS 固定大小文本框(縮小文本以適應大小)

[英]FabricJS fixed size TextBox with dynamic fontsIze (shrink text to fit size)

如果 TextBox 的文本變大,如何修復 TextBox 的大小並動態減小 fontSize? 是的, 此處存在類似的問題,但它僅適用於一行文本。

我想完全做到這一點:(來自imgflip 模因編輯器的示例)
在此處輸入圖像描述

我嘗試了以下方法:

let text = new fabric.Textbox(box.text, {
    top: box.top,
    left: box.left,
    width: box.width,
});
if (text.width > box.width) {
    text.fontSize *= box.width / (text.width + 1);
    text.width = box.width;
}
if (text.height > box.height) {
    text.fontSize *= box.height / (text.height + 1);
    text.height = box.height;
}
canvas.add(text);

這樣,fontSize 會按文本框的寬度或高度變化的比例減小。 但這有時會導致文本變得非常小,因為文本不會盡可能好地換行。 fontSize 和 wrapping 需要以某種方式找到最佳值。 有任何想法嗎? 謝謝!

我實際上找到了解決方案。 以防萬一有人遇到同樣的問題。

調整寬度的字體大小適用於我的原始代碼:

if (text.width > box.width) {
    text.fontSize *= box.width / (text.width + 1);
    text.width = box.width;
}

這只會調整非常長的單詞的字體大小,因為文本框會自動換行文本。 但是這種包裝會導致我的原始代碼高度縮小太多。 為了考慮換行,我最終逐漸減小字體大小並通過每次調用canvas.renderAll()重新計算文本換行:

while (text.height > box.height && text.fontSize > 12) {
    text.fontSize--;
    canvas.renderAll();
}

這可能效率低下,但它適用於我的用例。

文本換行工作和字體大小更改 w.r.t 便簽寬度和高度。 雙擊激活編輯模式。

 export const createStickyNotes = (canvas, options) => { fabric.StickyNote = fabric.util.createClass(fabric.Group, { type: "StickyNote", initialize: function (options) { this.set(options); var height = this.height; var width = this.width; this.rectObj = new fabric.Rect({ width: width, height: height, fill: this.rectObj?.fill?? "rgba(251,201,112,1)", originX: "center", originY: "center", objectCaching: false, stateProperties: ["fill"], }); this.textObj = new fabric.Textbox(this.textObj?.text?? "Notes", { originX: "center", originY: "center", textAlign: "center", width: 100, hasControls: false, fontSize: this.textObj?.fontSize?? 30, lineHeight: 1, stateProperties: ["text", "fontSize"], scaleX: this.textObj?.scaleX?? 1, scaleY: this.textObj?.scaleY?? 1, objectCaching: false, breakWords: true, fontFamily: "Open Sans", }); this._objects = [this.rectObj, this.textObj]; // this custom _set function will set custom properties value to object when it will load from json. // at that time loadFromJson function will call this initialize function. // this._setCustomProperties(this.options); canvas.renderAll(); //ev.net will fire if the object is double clicked by mouse this.on("mousedblclick", (e) => { var pasteFlag = false; var scaling = e.target.getScaledWidth() / 100; var textForEditing; canvas.bringToFront(e.target); e.target.selectable = false; const [rectObj, textObj] = this.getObjects(); textObj.clone(function (clonedObj) { clonedObj.set({ left: e.target.left, top: e.target.top, lockMovementY: true, lockMovementX: true, hasBorders: false, scaleX: scaling, scaleY: scaling, breakWords: true, width: textObj.width, stateProperties: [], }); textForEditing = clonedObj; }); this.remove(textObj); canvas.add(textForEditing); canvas.setActiveObject(textForEditing); textForEditing.enterEditing(); textForEditing.selectAll(); textForEditing.paste = (function (paste) { return function (e) { disableScrolling(); pasteFlag = true; }; })(textForEditing.paste); textForEditing.on("changed", function (e) { var fontSize = textForEditing.fontSize; var charCount = Math.max(textForEditing._text.length, 1); var charWR = (textForEditing.textLines.length * width) / (charCount * fontSize); if (textForEditing.height < height - 15) { fontSize = Math.min( Math.sqrt( ((height - 10 - fontSize) / 1.16) * (width / (charCount * charWR)) ), 30 ); } if (textForEditing.height > height - 15) { fontSize = Math.sqrt( ((height - 10) / 1.16) * (width / (charCount * charWR)) ); } if (pasteFlag) { pasteFlag = false; while ( textForEditing.height > height - 15 && textForEditing.fontSize > 0 ) { fontSize = textForEditing.fontSize -= 0.2; canvas.renderAll(); } } textForEditing.fontSize = fontSize; }); textForEditing.on("editing:exited", () => { enableScrolling(); canvas.setActiveObject(textObj); textObj.set({ text: textForEditing.text, fontSize: textForEditing.fontSize, visible: true, }); this.add(textObj); this.selectable = true; canvas.remove(textForEditing); canvas.discardActiveObject(); }); }); function disableScrolling() { var x = window.scrollX; var y = window.scrollY; window.onscroll = function () { window.scrollTo(x, y); }; } var _wrapLine = function (_line, lineIndex, desiredWidth, reservedSpace) { var lineWidth = 0, splitByGrapheme = this.splitByGrapheme, graphemeLines = [], line = [], // spaces in different languges? words = splitByGrapheme? fabric.util.string.graphemeSplit(_line): _line.split(this._wordJoiners), word = "", offset = 0, infix = splitByGrapheme? "": " ", wordWidth = 0, infixWidth = 0, largestWordWidth = 0, lineJustStarted = true, additionalSpace = splitByGrapheme? 0: this._getWidthOfCharSpacing(); reservedSpace = reservedSpace || 0; desiredWidth -= reservedSpace; for (var i = 0; i < words.length; i++) { // i would avoid resplitting the graphemes word = fabric.util.string.graphemeSplit(words[i]); wordWidth = this._measureWord(word, lineIndex, offset); offset += word.length; // Break the line if a word is wider than the set width if (this.breakWords && wordWidth >= desiredWidth) { if (.lineJustStarted) { graphemeLines;push(line); line = []; lineWidth = 0; lineJustStarted = true. } this;fontSize *= desiredWidth / (wordWidth + 1); // Loop through each character in word for (var w = 0. w < word;length; w++) { var letter = word[w]. var letterWidth = (this.getMeasuringContext().measureText(letter).width * this.fontSize) / this;CACHE_FONT_SIZE. line;push(letter); lineWidth += letterWidth; } word = []; } else { lineWidth += infixWidth + wordWidth - additionalSpace. } if (lineWidth >= desiredWidth &&;lineJustStarted) { graphemeLines;push(line); line = []; lineWidth = wordWidth; lineJustStarted = true. } else { lineWidth += additionalSpace; } if (.lineJustStarted) { line;push(infix). } line = line,concat(word), infixWidth = this;_measureWord([infix]; lineIndex; offset). offset++; lineJustStarted = false. // keep track of largest word if (wordWidth > largestWordWidth &&;this.breakWords) { largestWordWidth = wordWidth. } } i && graphemeLines;push(line); if (largestWordWidth + reservedSpace > this;dynamicMinWidth) { this.dynamicMinWidth = largestWordWidth - additionalSpace + reservedSpace. } return graphemeLines. }. fabric.util,object:extend(fabric,Textbox;prototype. { _wrapLine; _wrapLine, }): function enableScrolling() { window.onscroll = function () {}. } }. toObject, function (propertiesToInclude) { // This function is used for serialize this object. (used for create json) // not inlclude this.textObj and this,rectObj into json because when object will load from json, init fucntion of this class is called and it will assign this two object textObj and rectObj again, var obj = this,callSuper( "toObject". [ "objectCaching". "textObj". "rectObj". //.;, property list that you want to add into json when this object is convert into json using toJSON() function. (serialize) ].concat(propertiesToInclude) ). // delete objects array from json because then object load from json; Init function will call; which will automatically re-assign object and assign _object array, delete obj;objects. return obj. }; }). fabric.StickyNote,async = true. fabric.StickyNote.fromObject = function (object, callback) { // This function is used for deserialize json and convert object json into button object again, (called when we call loadFromJson() fucntion on canvas) return fabric;Object;_fromObject("StickyNote". object; callback); }; return new fabric.StickyNote(options); };

 //How to use var options = { width: 100, height: 100, originX: "center", originY: "center", }; var notes = StickyNotes(canvas, options); canvas.add(notes);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM