Canvas/FabricJS 中的对话泡泡?
Speech bubbles in Canvas/FabricJS?
正在寻找一种在我网站的 FabricJS 中制作常规对话泡泡的方法 canvas。在你标记这个 post 之前,我 做了 看到了 this question,它没有正确的答案并且是为 WordPress 设计的所以它对我没有特别的用处.
我想要的很清楚:一个带有文本的对话泡泡和一个 tail/handle,您可以拖动它以将其指向某物。
我找到了 this library 但我似乎无法在我的 FabricJS 中显示它 canvas?如果您能向我解释如何将此库添加到我的 canvas 中或提供另一种制作对话泡泡的方法,那就太棒了。
我对 Fabric.js 进行了一些研究,并设法创建了一个程序对话泡泡,但我无法快速将其转换为 Fabric.js class(这会使如果你想在你的 canvas 上有多个对话泡泡,请注意)。也许它对您或其他人仍然有帮助 https://codepen.io/timohausmann/pen/poywXzg
它主要是创建一个文本框,并根据文本的边界框更新它周围的矩形的位置。
var bound = textbox.getBoundingRect();
rect.left = bound.left - boxPadding;
rect.top = bound.top - boxPadding;
rect.width = bound.width + (boxPadding*2);
rect.height = bound.height + (boxPadding*2);
对于尾巴,我只是创建了一个透明的 Rect,您可以拖动它并使用它的坐标在“句柄”和文本框中心之间绘制一个具有三个点的多边形 [A]
。为了确保无论位置如何,尾巴都保持一定的宽度,我计算了句柄和对话气泡中心之间的度数 [B]
。为了保持文本框和句柄的位置同步,我计算了文本框移动了多少,然后简单地将差异添加到句柄位置 [C]
.
//calculate degree between textbox and handle [B]
var angleRadians = Math.atan2(handle.top - textbox.top,
handle.left - textbox.left);
var offsetX = Math.cos(angleRadians + (Math.PI/2));
var offsetY = Math.sin(angleRadians + (Math.PI/2));
//update the polygon [A]
poly.points[0].x = handle.left;
poly.points[0].y = handle.top;
poly.points[1].x = textbox.left - (offsetX * arrowWidth);
poly.points[1].y = textbox.top - (offsetY * arrowWidth);
poly.points[2].x = textbox.left + (offsetX * arrowWidth);
poly.points[2].y = textbox.top + (offsetY * arrowWidth);
//update the handle when the textbox moved [C]
if(textbox.left !== textbox.lastLeft ||
textbox.top !== textbox.lastTop) {
handle.left += (textbox.left - textbox.lastLeft);
handle.top += (textbox.top - textbox.lastTop);
handle.setCoords();
}
免责声明:我不是 Fabric.js 专家,也许图书馆有一些捷径。
@Til Hausmann 的回答很好(谢谢!)。
但是,当我尝试存储和加载 canvas 数据(分别通过 canvas.toJSON
和 canvas.loadFromJSON
时,我 运行 遇到了一些问题。
经过一些摆弄,这可以通过
解决
- 在
updateBubble()
方法中为两个多边形存储lastLeft
和lastTop
:
poly.lastLeft = Math.min(handle.left, textBox.left);
poly.lastTop = Math.min(handle.top, textBox.top);
- 在加载数据后设置多边形的
left
/ top
属性:
canvas.loadFromJSON(jsonData, () => {
const poly = // ...
const poly2 = // ...
poly.left = poly.lastLeft;
poly.top = poly.lastTop;
poly2.left = poly2.lastLeft;
poly2.top = poly2.lastTop;
// ...
// Important:
canvas.renderAll();
});
- 将全套形状属性传递给
canvas.toJSON()
canvas.toJSON(
['lastLeft', 'lastTop'].concat(
Object.keys(handleProperties),
Object.keys(polyProperties),
Object.keys(poly2Properties),
Object.keys(textRectProperties)
))
令我惊讶的是第 (3) 步实际上是必要的,但没有它就无法工作...
正在寻找一种在我网站的 FabricJS 中制作常规对话泡泡的方法 canvas。在你标记这个 post 之前,我 做了 看到了 this question,它没有正确的答案并且是为 WordPress 设计的所以它对我没有特别的用处.
我想要的很清楚:一个带有文本的对话泡泡和一个 tail/handle,您可以拖动它以将其指向某物。
我找到了 this library 但我似乎无法在我的 FabricJS 中显示它 canvas?如果您能向我解释如何将此库添加到我的 canvas 中或提供另一种制作对话泡泡的方法,那就太棒了。
我对 Fabric.js 进行了一些研究,并设法创建了一个程序对话泡泡,但我无法快速将其转换为 Fabric.js class(这会使如果你想在你的 canvas 上有多个对话泡泡,请注意)。也许它对您或其他人仍然有帮助 https://codepen.io/timohausmann/pen/poywXzg
它主要是创建一个文本框,并根据文本的边界框更新它周围的矩形的位置。
var bound = textbox.getBoundingRect();
rect.left = bound.left - boxPadding;
rect.top = bound.top - boxPadding;
rect.width = bound.width + (boxPadding*2);
rect.height = bound.height + (boxPadding*2);
对于尾巴,我只是创建了一个透明的 Rect,您可以拖动它并使用它的坐标在“句柄”和文本框中心之间绘制一个具有三个点的多边形 [A]
。为了确保无论位置如何,尾巴都保持一定的宽度,我计算了句柄和对话气泡中心之间的度数 [B]
。为了保持文本框和句柄的位置同步,我计算了文本框移动了多少,然后简单地将差异添加到句柄位置 [C]
.
//calculate degree between textbox and handle [B]
var angleRadians = Math.atan2(handle.top - textbox.top,
handle.left - textbox.left);
var offsetX = Math.cos(angleRadians + (Math.PI/2));
var offsetY = Math.sin(angleRadians + (Math.PI/2));
//update the polygon [A]
poly.points[0].x = handle.left;
poly.points[0].y = handle.top;
poly.points[1].x = textbox.left - (offsetX * arrowWidth);
poly.points[1].y = textbox.top - (offsetY * arrowWidth);
poly.points[2].x = textbox.left + (offsetX * arrowWidth);
poly.points[2].y = textbox.top + (offsetY * arrowWidth);
//update the handle when the textbox moved [C]
if(textbox.left !== textbox.lastLeft ||
textbox.top !== textbox.lastTop) {
handle.left += (textbox.left - textbox.lastLeft);
handle.top += (textbox.top - textbox.lastTop);
handle.setCoords();
}
免责声明:我不是 Fabric.js 专家,也许图书馆有一些捷径。
@Til Hausmann 的回答很好(谢谢!)。
但是,当我尝试存储和加载 canvas 数据(分别通过 canvas.toJSON
和 canvas.loadFromJSON
时,我 运行 遇到了一些问题。
经过一些摆弄,这可以通过
解决- 在
updateBubble()
方法中为两个多边形存储lastLeft
和lastTop
:
poly.lastLeft = Math.min(handle.left, textBox.left);
poly.lastTop = Math.min(handle.top, textBox.top);
- 在加载数据后设置多边形的
left
/top
属性:
canvas.loadFromJSON(jsonData, () => {
const poly = // ...
const poly2 = // ...
poly.left = poly.lastLeft;
poly.top = poly.lastTop;
poly2.left = poly2.lastLeft;
poly2.top = poly2.lastTop;
// ...
// Important:
canvas.renderAll();
});
- 将全套形状属性传递给
canvas.toJSON()
canvas.toJSON(
['lastLeft', 'lastTop'].concat(
Object.keys(handleProperties),
Object.keys(polyProperties),
Object.keys(poly2Properties),
Object.keys(textRectProperties)
))
令我惊讶的是第 (3) 步实际上是必要的,但没有它就无法工作...