我如何在fabricjs圈周围绘制字母

时间:2015-12-08 17:32:20

标签: javascript loops canvas html5-canvas fabricjs

我有一个圆圈添加到画布,然后一些文字我想环绕一个圆圈。 这是我到目前为止所拥有的

var circle = new fabric.Circle({
  top: 100,
  left: 100,
  radius: 100,
  fill: '',
  stroke: 'green',
});
canvas.add(circle);

var obj = "some text"

for(letter in obj){             
  var newLetter = new fabric.Text(obj[letter], {
    top: 100,
    left: 100
});

canvas.add(newLetter);
canvas.renderAll();
}

我在网上发布了一些其他解决方案,但到目前为止还没有任何正常的结构。

1 个答案:

答案 0 :(得分:2)

圆形文字。

我开始回答这个问题,认为这很容易,但有点难看。我把它推回到更简单的版本。

我遇到的问题是基本的,但没有简单的解决方案..

  • 围绕圆圈的文字最终可能会颠倒过来。不好的 读
  • 间距。因为画布只能提供基本的2D变换 不能独立缩放文本的顶部和底部 文字看起来太宽或太宽。

我有一个完全另类的方法,因为它太重了,无法在这里得到答案。它涉及一个自定义扫描线渲染(各种GPU硬件),因此如果文本质量至关重要,您可以尝试沿着这些线寻找某些东西。

我遇到的问题是通过忽略它们来解决的,总是一个很好的解决方案。 LOL

如何在2D画布上渲染圆形文字。

由于在一次调用中无法做到这一点,我编写了一个函数,每次渲染一个角色。我使用ctx.measureText来获取要绘制的整个字符串的大小,然后将其转换为角度像素大小。然后稍微调整各种选项,对齐,拉伸和方向(镜像),我一次一个地查看字符串中的每个字符,使用ctx.measureText来测量它的大小,然后使用{ {1}}定位旋转并缩放角色,然后只需调用ctx.setTransform渲染该角色。

它比ctx.fillText()方法慢一点,但填充文字无法在圆圈上绘制。

需要进行一些计算。

为了锻炼,给定半径的像素的角度大小是微不足道的,但我常常看不到正确的。因为Javascript在弧度下工作,角度像素大小只是

ctx.fillText()

因此,要训练一些文字占据圆圈或给定半径的角度。

var angularPixelSize = 1 / radius; // simple

锻炼单个角色的大小。

var textWidth = ctx.measureText("Hello").width;
var textAngularWidth = angularPixelSize * textWidth;

因此,您可以使用角度大小来对齐圆圈上的文本,无论是居中,右侧还是左侧。有关详细信息,请参阅代码段。

然后你需要一次一个地遍历每个角色,计算变换,渲染文本,为下一个角色移动正确的角距离,直到完成。

var text = "This is some text";
var index = 2; // which character
var characterWidth = ctx.measureText(text[index]).width;
var characterAngularWidth = angularPixelSize * textWidth;

繁琐的数学部分正在设置变换。我发现直接使用转换矩阵更容易,这使得我可以使用缩放等操作,而不必使用太多的转换调用。

设置变换需要6个数字,前两个是x轴的方向,接下来的两个是y轴的方向,后两个是从画布原点的平移。

所以要获得Y轴。对于每个角色,圆心向外移动的线我们需要角色绘制的角度,并减少不对齐(注意减少不消除)角宽度,这样我们就可以使用角色的中心来对齐它。

var angle = ?? // the start angle
for(var i = 0; i < text.length; i += 1){ // for each character in the string
    var c = text[i]; // get character
    // get character angular width
    var w = ctx.measureText(c).width * angularPixelSize;
    // set the matrix  to align the text. See code under next paragraph 
    ...
    ...
    // matrix set
    ctx.fillText(c,0,0); // as the matrix set the origin just render at 0,0
    angle += w;
}

现在我们有了标准化的矢量,它将是x轴。角色沿此轴从左向右绘制。我一次构建矩阵,但我将在下面分解它。请注意我在我的代码片段中用角度做了一个嘘声,所以代码是回到前面(X是Y,Y是X) 请注意,该代码段能够在两个角度之间拟合文本,因此我缩放x轴以允许此操作。

// assume angle is position and w is character angular width from above code
var xDx = Math.cos(angle + w / 2); // get x part of X axis direction
var xDy = Math.sin(angle + w / 2); // get y part of X axis direction

那就是绘制圆形字符串的数学和逻辑。我很抱歉,但我不使用fabric.js所以它可能有也可能没有选项。但是您可以创建自己的函数并直接渲染到与fabric.js相同的画布,因为它不排除访问。虽然在Fabric.js不知道状态变化时会保存并恢复画布状态。

以下是在实践中显示上述内容的片段。它远非理想,但是使用现有的canvas 2D API可以快速完成。 Snippet具有测量和绘图的两个功能以及一些基本用法示例。

&#13;
&#13;
// assume scale is how much the text is squashed along its length. 
ctx.setTransform(
    xDx * scale, xDy * scale, // set the direction and size of a pixel for the X axis
    -xDy, xDx,                // the direction ot the Y axis is perpendicular so switch x and y 
    -xDy * radius + x, xdx * radius + y  // now set the origin by scaling by radius and translating by the circle center
);
&#13;
&#13;
&#13;