gpt4 book ai didi

fabricjs - 织物 JS : Text object's selection area is larger than the actual size of text

转载 作者:行者123 更新时间:2023-12-04 20:30:51 26 4
gpt4 key购买 nike

我们正在使用 Fabric JS 向 Canvas 添加文本和图像对象。

但是当我们添加任何文本对象并选择它时,它显示的选择区域大于文本的实际大小。

Please refer this link to see the screen-shot.

我们正在使用以下代码添加文本对象。

var text_object = new fabric.Text('00', {
字体大小:192,
fontFamily: 'Times New Roman',
填充: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);

主要问题是当我们尝试获取添加的文本对象的宽度和高度时;它为我们提供了文本对象选择区域的宽度和高度,而不是文本的实际大小。

我们怎样才能使文本对象的选择区域与文本的实际大小相同?

或者我们如何在没有选择区域的情况下获得文本的实际大小?

最佳答案

没有直接的方法可以实现您想要的,那就是文本矢量路径的边界框。

如果您对近似解决方案没问题,请将文本渲染到空 Canvas 上,使用 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 并不是特别快)。知道了这一点,您可能会想尝试减小 Canvas 大小而不使用与目标 Canvas 相同的 Canvas ,但我建议您不要这样做,因为它会引入与下一点相关的新问题。
  • 如果您在文本超出 Canvas 的情况下进行测量,则边界框将被限制在可见区域内(它将粘在边框上)。如果碰巧获得真正的宽度和高度,您可能会考虑增加 Canvas 大小,但如果您不限制字体大小和文本数量,您可能会以 Canvas 结束,这样会减慢浏览器的速度,或者可能甚至让它崩溃......所以我会接受边界框粘在边界上。您可能会考虑使用 measureText 提供的宽度。可能会有所帮助,但不幸的是,要获得扫描完整图像所需的顶部和高度。
  • 关于fabricjs - 织物 JS : Text object's selection area is larger than the actual size of text,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46903838/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com