Reputation: 469
Good day, reader.
I am using Konva.TextPath, to create curved text. I am calculating path based on text length and angle it should be curved(ex. from 270 to 90 is half curved , 359 from 0, is nearly the circle it self). When I pass path to Konva.Path, it draws perfectly, but with TextPath (in some cases ) it renders with without last letters, and with wrong letter spacings. I have seen this issue on github, but I am not sure if this is same issue.
You can see attached pictures, with it's paths You can find calculations on codesandbox
If more info needed please ask.
Thanks.
Path 1
M6.587352859507078 6.779702002611884,
A665.1292665214339, 665.1292665214339, 0, 0, 0, 271.78815041484745 4.465329704342594
Path 2
M8.968283494812425 14.597383097232182,
A993.126844893427, 993.126844893427, 0, 0, 0, 268.2165426505044 12.334957814595896
Upvotes: 0
Views: 481
Reputation: 9535
This is not an answer but provides some insight into a potential DIY solution in case you need it.
Generically, the algorithm for text on a path is conceptually simple but a bit of a hassle to implement. Konva gives you the same facilities as raw HTML5 canvas commands in respect to this task so there is no need to abandon Konva.
The concept is
The complex step is 3 because there is no way to predict the path. It 'could' be a straight line, or a circle, or an ellipse, but you have to assume an unpredictable mad jagged loopy thing.
I am ignoring any alignment or extra character padding to keep things simple.
For each character , you will know the starting point (x, y) to draw - this is the start of the path for the first character , and the end point of the previous character for every subsequent character in the string. Knowing the starting point is good, now you have to find the end point of the character space.
A quick discussion of the path.getPointAtLength() method is required now. The canvas knows the length of any path you ask it to draw, and you can ask it the (x, y) point for any distance along that path (The Konva source has code for this - it's an interesting read!). So, given a path of length of say 100, you can ask for the (x, y) point at length 42 with path.getPointAtLength(42) and Konva will tell you.
So what ? We can use that to go fishing for the character end point on the curve.
You will need an algorithm that does this:
What you want is a binary chop approach so that your steps reduce each time thus reaching perfection at some point. Although you should define a tolerance so as to give up when a close-enough point is found.
Remember, what you are doing here is feeling for the point on the path where the end-point of the character you want to draw will look reasonable.
Once you have the character positions you do a little more math to work out the rotation angle and top-left position of each character. You can then output the text.
If you need alignment or character spacing you can add those features quite easily once you have the main algorithm running.
There's a similar blog post on my blog.
Have fun.
Upvotes: 2
Reputation: 20363
Look like the rendering logic of Konva.TextPath
is just not perfect, so it has inconsistent letter spacings.
About the missing last letter. You are calculating text width as
const textLength =
textNode.getTextWidth() +
(textNode.text().length - 1) * textNode.letterSpacing();
That is a correct solution for straight Konva.Text
, but Konva.Path
is using approximations when rendering over the specified path. So resulted text may take a larger length. So there is no space for the last letter. As workaround you can slightly increase textLength
. For example by adding textNode.fontSize()
.
Upvotes: 0