簡體   English   中英

Fabric JS:文本對象的選擇區域大於文本的實際大小

[英]Fabric JS: Text object's selection area is larger than the actual size of text

我們正在使用Fabric JS將文本和圖像對象添加到畫布。

但是當我們添加任何文本對象並選擇它時,它會顯示大於文本實際大小的選擇區域。

請參閱此鏈接以查看屏幕截圖。

我們使用以下代碼添加文本對象。

var text_object = new fabric.Text('00', {
                    fontSize: 192,
                    fontFamily: 'Times New Roman',
                    padding: 0
                  });
text_object.top = parseInt((canvas.height - text_object.height) / 2);
text_object.left = parseInt((canvas.width - text_object.width) / 2);
text_object.lockUniScaling = true;
canvas.add(text_object);
canvas.renderAll();
canvas.setActiveObject(text_object);

主要問題是當我們嘗試獲取添加的文本對象的寬度和高度時; 它給出了文本對象選擇區域的寬度和高度,而不是文本的實際大小。

我們如何使文本對象的選擇區域與文本的實際大小相同?

或者如何在沒有選擇區域的情況下獲得文本的實際大小?

沒有直接的方法來實現你想要的東西,那就是文本矢量路徑的邊界框。

如果您對近似解決方案沒問題,請將文本渲染到空白畫布,使用getImageData檢查所有像素的透明度,並計算出找到填充點的最大值和最小值x和y。 它遠非完美,但你不會輕易獲得更好的解決方案。

我想可能有解決方案服務器端,但我不知道任何。

從理論上講,你可以在JS中創建自己的字體渲染引擎,因此你可以擁有完美的邊界框,但除了簡單/玩具外,一個嚴肅的文本布局引擎需要數年和數年才能實現,所以我想這完全超出了范圍。

如果您需要有關近似方法的幫助,請告訴我並提供一個示例。

編輯提供一個例子:

 function getVisiblePixelsBoundingBox(canvas) { const context = canvas.getContext("2d"); const imageData = context.getImageData(0, 0, canvas.width, canvas.height).data; let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity; for (let y = 0; y < canvas.height; y++) { for (let x = 0; x < canvas.width; x++) { const alpha = imageData[(y * canvas.width + x) * 4 + 3]; if (alpha > 0) { minX = Math.min(minX, x); minY = Math.min(minY, y); maxX = Math.max(maxX, x); maxY = Math.max(maxY, y); } } } return { left: minX, top: minY, width: maxX - minX, height: maxY - minY }; } // you will need to create a new canvas var canvas = document.createElement("canvas"), context = canvas.getContext("2d"); // and set the width and height the same as the canvas you want to draw the text // here I'm just adding some values for the example: canvas.width = 600; canvas.height = 400; // now I'm going to draw some text on it context.font = "120px serif"; context.fillText("Lipsum", 100, 200); let boundingBox = getVisiblePixelsBoundingBox(canvas); // now this is not needed in your case, but want to see the canvas and // I will draw a rectangle around the bounding box to see how it works: document.body.appendChild(canvas); context.strokeStyle = "red"; context.strokeRect(boundingBox.left, boundingBox.top, boundingBox.width, boundingBox.height); 

好的,所以這似乎很好,但要注意這些問題:

  • 精度僅限於像素,因此盡管繪制邊界框完全沒有問題,但對於需要更高精度的操作(如完美對齊形狀)而言並不好。 此外,由於測量方法,如果形狀的一部分太薄而根本看不到,那么它將無法測量(對您來說可能不是一個大問題,因為這樣的極薄形狀不會發生在字體)。

  • 執行它可能會很慢,因為我們正在迭代所有像素以獲得結果(並且JS並不特別快)。 知道這一點,你可能會試圖減少畫布大小而不使用目標畫布的相同畫布,但我建議你不要這樣做,因為它會引入與下一個點相關的新問題。

  • 如果您使用文本進行測量超出畫布,則邊界框將限制在可見區域(它將粘貼到邊框)。 你可以考慮增加畫布大小,如果這恰好得到真正的寬度和高度,但如果你不限制字體大小和文本數量,你可能會以畫布這么大來減慢瀏覽器的速度或者可能甚至崩潰了......所以我只是接受邊界框粘在邊界上。 您可能會認為使用measureText提供的寬度可能有所幫助,但不幸的是,要獲得掃描整個圖像所需的頂部和高度。

暫無
暫無

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

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