繁体   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