Hi
Loving the product but we desperatly need curve text. I've seen that it's on the roadmap but would like to ask if there is any progress or anything that can be done to help?
Great work guys!
There is a $200 open bounty on this issue. Add to the bounty at Bountysource.
Have you looked at something like this:
http://tympanus.net/Development/Arctext/
Or is the challenge to get curved text in the canvas with object controls?
On Mon, Jul 1, 2013 at 9:20 AM, dean555 [email protected] wrote:
Hi
Loving the product but we desperatly need curve text. I've seen that it's
on the roadmap but would like to ask if there is any progress or anything
that can be done to help?Great work guys!
ā
Reply to this email directly or view it on GitHubhttps://github.com/kangax/fabric.js/issues/729
.
Hi mojo5000
We need it to work with fabric :(
I need this functionality as well. I'm using fabric to create a T-shirt designer app. I think this is a common app using fabric. All good T-shirt apps allow text warping. It is huge in T-shirt design. Please someone write this!! Fabric is 99% perfect and this is the missing link!
I am working on T-shirt designer app as well. I wonder if we should join hands rather than competing with each other ;). BTW check out the https://github.com/imomin/fabric.curvedText.
I tried the new code but still can't get it to work for me. Are you able to use this code to curve text successfully? I'm working on a t-shirt app that will have layers similar to photoshop w/ hide/lock functions for each layer/canvas item. Can you post a jsfiddle of this working for you?
Here you go! http://jsfiddle.net/NHs8t/
@imomin you are a godsend thx
Hi @imomin
Nice work but you cannot make the text straight also you have 3 sliders. Can we make it using one single slider so that user adds a text which is straight and then he can curve it up/down using a slider.
And the curve text should also work with load from SVG and JSON and export as well.
But excellent job till now.
@dean555
FYI, I pulled somebody else's project and made minor changes. So, the credit goes to him.
In my project I am using only spacement slider with curve up, curve down and in-line button.
Based on the option selected, curve up/down or in-line I swap between Curve Text or standard Text object.
I started my project few weeks ago and I haven't got to SVG/JSON export yet. I will make changes to it as I move forward.
I noticed its a group of fabric.text objects is there any performance advantages of using this rather than rendering each letter individually?
Hi all,
I've just started with fabricjs a few weeks ago. Since I want to work with curved text, I've implemented your code into my project.
My question will probably seem very stupid for you (actually, I am a beginner), but I would like to know how you can select the text group, like "canvas.getActiveObject()" for a regular text ?
I hope I will get a reply. Anyway, thanks to Imomin & Skritz for your amazing work.
ps : sorry for my english level, I am french
I started to work on my own curved text, I am NEW to fabric and OO javascript and HTML5/Canvas, so I am having some issues trying to make it work.
Any hint would be greatly appreciated.
My Goal is to make a fabric object that acts like the others (getText, setText, set properties, export SVN, JSON, etc...)
In your $(function(){....} on line 643 add var canvas = new fabric.Canvas('c'); and add comma after left:50,.Hopefully this will help you move forward. http://jsfiddle.net/t4VPQ/14/
yes, Thank you, saw that after I updated the comment :-) was a copy/paste error. The problem is that I can't seems to render the text on the main canvas.
Ok, a lot of functionality is ready... I just can't figure it out how to refresh the render on the fly.. dang
I have a almost fully working example. I need to figure out how to make the resize work as well as test the exports (SVG and jSON)
Nice work @EffEPi :) I was really looking towards this feature
I was actually thinking of implementing a SVG like method http://www.svgbasics.com/text2.html
http://www.html5canvastutorials.com/kineticjs/html5-canvas-kineticjs-text-path-tutorial/
That gives me a new idea.. freehand Text. Using the drawing mode create a path and then set the text around that path.. but this is out of the scope of this thread
A bit like http://csswarp.eleqtriq.com/ ? :)
Yeah, looks pretty badass. We're planning to have text-on-path sometime in
the future!
On Sun, Sep 29, 2013 at 5:22 PM, tiredenzo [email protected] wrote:
A bit like http://csswarp.eleqtriq.com/ ? :)
ā
Reply to this email directly or view it on GitHubhttps://github.com/kangax/fabric.js/issues/729#issuecomment-25322161
.
@EffEPi : Whoaaaaaw! I wish I had your skills...
@Jochuaf let me know if you have any improvements for it. I am already planning on a new rewrite that maybe doesn't use grouping and export to SVN as paths and also imports from path... to do that I have to learn SVN rendering a bit better
EffEPi : thanks for the answer. I've managed to implement your code into my the project I am working on (light product customizer). I have to say it works very well. Attaching text to path would be also great and I think I wouldn't be the only one interested in that :-)
Hi everyone
Have there been any developments with getting curve text to work? getting desperate now... :(
@EffEPi how would you do this extending from IText instead of Text? I need the text to be editable.
Has anyone solved this issue yet? My site is waiting on a solution that uses a slider to curve text. Willing to pay a developer to develop this.
@goldguy23 no solution yet and there's too much other stuff for me to go through until I can get to this. There's already $100 bounty on this, but this is almost certainly very small for a feature like this (worth at least 1K+; a lot of stuff to consider)
If I made the bounty 1000 when do you think you could work on this. We are trying to launch our new site by mid September. If you can't get to this then I understand and we would just wait another year as it's a nice to have not a need to have.
Marc Goldberg
Founder
www.tasseltoppers.com
On Aug 6, 2014, at 8:09 AM, Juriy Zaytsev [email protected] wrote:
@goldguy23 no solution yet and there's too much other stuff for me to go through until I can get to this. There's already $100 bounty on this, but this is almost certainly very small for a feature like this (worth at least 1K+; a lot of stuff to consider)
ā
Reply to this email directly or view it on GitHub.
No time to work on this now, sorry.
kangax
On Wed, Aug 6, 2014 at 2:27 PM, goldguy23 [email protected] wrote:
If I made the bounty 1000 when do you think you could work on this. We are
trying to launch our new site by mid September. If you can't get to this
then I understand and we would just wait another year as it's a nice to
have not a need to have.Marc Goldberg
Founder
www.tasseltoppers.comOn Aug 6, 2014, at 8:09 AM, Juriy Zaytsev [email protected]
wrote:@goldguy23 no solution yet and there's too much other stuff for me to go
through until I can get to this. There's already $100 bounty on this, but
this is almost certainly very small for a feature like this (worth at least
1K+; a lot of stuff to consider)ā
Reply to this email directly or view it on GitHub.ā
Reply to this email directly or view it on GitHub
https://github.com/kangax/fabric.js/issues/729#issuecomment-51327514.
@maza23 don't have much time for extending this right now, but as soon as I can I will
@goldguy23 have you looked at my plugin ? maybe it will be a nice patch until you can have a fully supported curved text
@EffEPi We have spent many hours trying to manipulate the plugin you have created but are not able to get it on a simple sliding bar to bend the text evenly upwards and downwards. We cannot get the spacing right. We will wait patiently for a solution
Can you make a jfiddle and post it so I can check the problem?
Sent via the Samsung GALAXY S®4, an AT&T 4G LTE smartphone
ā
Reply to this email directly or view it on GitHub.
Just uploaded a new version.
@goldguy23 I believe you want to look into the manipulation of the spacing and radius at the same time, as the radius decrease (start with a very high radius), the spacing needs to increase
@EffEPi where is the link to view the new changes?
I will create a fiddle very soon and add it to the page.
Sent via the Samsung GALAXY S®4, an AT&T 4G LTE smartphone
ā
Reply to this email directly or view it on GitHub.
I see you are adding a "Path" to the text to implement the curve feature,
that is not bad, but can you implement the range input to curve the text
instead of using the mouse drag and drop.
_From:_ lirmont [mailto:[email protected]]
_Sent:_ Wednesday, September 10, 2014 1:13 PM
_To:_ kangax/fabric.js
_Cc:_ goldguy23
_Subject:_ Re: [fabric.js] Curve Text Feature $200
In response to the bounty, I've added the ability to assign a fabric.Path
to a fabric.Text-like object (i.e. fabric.Text and fabric.IText). Demo
available here: http://darkabstraction.com/showOff/fabricjs/
[image: boing]
https://cloud.githubusercontent.com/assets/811142/4221828/81c46384-390d-11e4-942b-1e148d249b47.png
For the demo, be sure to hide the options when not in use for best
performance. Also, while the demo has a lot of features, it was primarily
used to test the actual curve text feature, so I do not guarantee that it
is bug free. It should also not be used as a reference, because I am not
familiar enough with Fabric.js to write code of that particular quality.
In-place solution (hotfix) available here (include it anytime after
fabric.js is loaded; it quietly extends fabric.Point, fabric.Path,
fabric.Text, and fabric.IText):
http://darkabstraction.com/showOff/fabricjs/CurveDependencies.prepatch.js
In-source solution has been pushed to github here:
https://github.com/lirmont/fabric.js/tree/Curve-Text
The only difference between the two solutions is that the in-place one has
an extra property, "debug", which, if true, will draw the bounding boxes it
uses.
I've likely missed some features as this is my first time using Fabric.js.
Point them out to me, and I'll fix them. You can reach me at:
https://twitter.com/lirmont
ā
Reply to this email directly or view it on GitHub
https://github.com/kangax/fabric.js/issues/729#issuecomment-55148545.
Thanksā¦
I would prefer it to have the same functionality as my current site:
https://www.tasseltoppers.com/design-your-own
Add text and then click on it. The curve feature sliding bar is the exact
same feature I am looking for.
_From:_ lirmont [mailto:[email protected]]
_Sent:_ Wednesday, September 10, 2014 1:42 PM
_To:_ kangax/fabric.js
_Cc:_ goldguy23
_Subject:_ Re: [fabric.js] Curve Text Feature $200
@goldguy23 https://github.com/goldguy23 I'd be happy to. As an
application of this feature (rather than the feature itself), that would be
another demo (demonstrating the feature). If you have a specific idea
(mock-up) or other reference, please send it my way. Otherwise, I can't
guarantee it'll be what you want. Thanks.
ā
Reply to this email directly or view it on GitHub
https://github.com/kangax/fabric.js/issues/729#issuecomment-55152876.
If this gets merged into fabric can the code for curved/path be refactored into a separate subclass, something like fabric.ITextPath? Kind of like how fabric.IText subclasses fabric.Text. That way it wont over complicate the already complicated IText while maintaining functionality plus it keeps the classes cleaner.
I noticed that but still, imo fabric.Text is fabric.Text not fabric.Text + feature xyz else they might as well have put fabric.IText into fabric.Text.
@lirmont can you confirm if this functionality supports loadFromJSON and toJSON fabricjs functions.
@lirmont we still need to implement that feature, otherwise the design cannot be saved/loaded. That would be the final step
Just found a perfect example for this @ http://www.ooshirts.com/designapp/#5cb3e31887764e15
I am having my developers look into this. Give me a few days. Thanks so much
One last question: Can this be used directly in an html range input? Is so, we can confirm that the functionality is ready to be used.
Ok great job!!!
_From:_ lirmont [mailto:[email protected]]
_Sent:_ Friday, September 26, 2014 6:00 PM
_To:_ kangax/fabric.js
_Cc:_ goldguy23
_Subject:_ Re: [fabric.js] Curve Text Feature $200
@goldguy23 https://github.com/goldguy23 There's nothing special about my
choice to choose fabric for the input. To use a regular range slider (i.e.
HTML element "input" with type="range"), you'd listen for the "input" event
on the range slider, look up the valueAsNumber beneath the target in the
event passed to the event handler, and then you're looking at a range of 0
to 100 (default). Because your specific concerns are about up and down, you
probably want this range divided into a positive and negative range (re: up
and down). So, you'll probably want to additionally specify the following
attributes on the slider: "min", "max", and "step". Values of -1, 1, and
0.01 will give you a range of two whole sets of numbers (i.e. from -1 to 0
and from 0 to 1). Driven by that number, you can alter the path object by
some arbitrary value, and then render the scene.
ā
Reply to this email directly or view it on GitHub
https://github.com/kangax/fabric.js/issues/729#issuecomment-57026068.
Hello there, anyone have example how make it work with multiple instance of text object? thank you
Hello,
Can we add this patch in node js server side also?
thank you
this patch will be merged soon. is not yet merged.
I have modified the text function to allow circular text. Im testing it and when i got it will publish here.
Hi @eseperio, thanks for looking into it.
We have an old PR from @lirmont that we have to update to work with current release.
We will try to pick up best from both implementation.
looking forward to see this functionality merged to official repo
Take a look here https://github.com/Eseperio/fabricText2
Hi Eseperio,
https://github.com/Eseperio/fabricText2
Please let me know how to use the code ?
do you have any js fiddle ?, please share so i can learn from it
Thanks
Take a look at this , that is using the function
http://codecanyon.net/item/woocommerce-vinyl-stickers-labels-design/11890236
Note: I“m not related the project mentioned before.
I have made a fork from fabric that updates @Eseperio's work from months ago to the current head of fabric. You can find that here:
I will have a look at it.
Hi,
I have been implemented curvedText class in my project with fabric.js and including all effects like curved,arc, smallToLarge, largeToSmallTop, largeToSmallBottom, bulge. Its works fine.
But cut-copy-paste issue. while copy & paste object, apply any text effect to one object, it effects to other also.
Can anybody please help me to fix it ?
I had already read comment "the problem is that I can't seems to render the text on the main canvas. "
what I should do to render text on the main canvas?
Thanks & Regards,
Mukesh
Hi,
I have also implemented the same,
Take a look over here,
https://github.com/swabha1/Path_Text_V0.2.git
It have capability of drawing text on any shape like Circle, Rectangle, Arc, Line, any Path, etc.
Thanks.
@swabha1
can you make a fiddle and show how it works...
Has curvedText been merged in? I see mention in the 1.5 changelog that curved text is coming but as of 1.7.3 I don't see it.
Has not been merged and probably it won't.
Is a nice feature but it is fine on a plugin.
There is no svg export compatibility
No idea how it should coope with textbox
Not tried with styles
As an update to the original request, has there been any progress on being able to have the text element match the curvature of an existing path? As of right now, the letters simply draw their own singular arc and follow that (oddly enough behaving curiously in respect to padding above and below letters).
Is there a way to get an SVG style textPath element? This would cover a number of more complex use cases involving an x^2 or more complex path that has already been drawn.
Here is a very simplistic example done using SVG and CSS, but I was wondering if there was a way to translate this directly to functionality in fabric by extending the existing curved text object plugin
https://css-tricks.com/snippets/svg/curved-text-along-path/
The company I represent has offered to put up a larger bounty to address the issue I mentioned in my previous post.
If anyone has any working module that supports the features mentioned there please contact via this thread.
Before anyone run to do it, just be esplicit that:
fabric master branch ( version 2.0 soon ) has a very different rendering rather than 1.7.x
and this i say for the company that could want to migrate to 2.0 at some point ( or maybe not )
For who is interested in open source committing:
fabric aims to support text on a path rather than just text on a circle.
fabric needs also svg export when add a visual feature.
@DevangCP : can you make a fiddle and show how it works... please
Hello,
I am trying to add text on path but not getting success.
https://github.com/swabha1/Path_Text_V0.2 i have used but lots of bug when use latest version of fabric
is this feature enabled on fabricjs 2.0.0-rc3? or still very much unsupported? thanks @kangax and @asturur and team!
I think I have a nice solution for everyone:
A real fabricjs object for curved/circular text. Note: this is not text-along-path, this is text-along-circle. It works in fabricjs-1.7.x and in 2.x.
https://jsfiddle.net/av01d/4p0syzw3/
For fabricjs-2.x, some very small changes might be needed, contact me if you can't get it to work.
maybe i can pull out text on path from it
Hi @av01d , had you any experiences to implement the toSVG() func?
No, I have not. And I'm afraid it won't be easy. How about you?
Op 16 feb. 2018 23:28 schreef "Alex Zaganelli" notifications@github.com:
Hi @av01d https://github.com/av01d , had you any experiences to implement
the toSVG() func?
ā
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/kangax/fabric.js/issues/729#issuecomment-366376807,
or mute
the thread
https://github.com/notifications/unsubscribe-auth/AF9U3rZdMid8OnOtc5MXdOZ2Q2HbYjGHks5tVgDvgaJpZM4Ax7k8
.
@av01d, would it be hard to make the text go back to normal straight line when slider is at its maximum? Also it looks like this does not support multiline text right?
@sideburn: Yes, that (straight line when slider at max) would be quite hard, as the technique to draw curved text differs completely from drawing regular text.
Multiline text is indeed not supported. But think about that for a bit: would it make sense?
How do you cope with lines of different length? I don't think multiline curved text makes any sense...
@dean555, @goldguy23: Care to follow up on your bounty?
Just to be clear, i will not merge any curve text feature.
Fabric.js aims at supporting text on path feature that is more flexible and can also support input and output to svg.
Text on a path can include text on a curve.
@asturur I understand your position, it will be a duplicated functionality, but it will be worth have a shorthand to to this. I mean making a function that prepares a circumference path to write text. As you can see there are many people requesting this function.
sure a shorthand is good, the point is that i m not gonna merge a curve only engine.
Just want to be clear, if someone wants to put efforts and personal time on this, should know what i expect to merge.
I think most people use this for simple design editors to place photos and text and make collages etc. like that T-shirt maker website. And one of the missing elements is a simple text bender so you can bent text around a photo or a circle. Text on path is too complicated and professional. Doesnāt need to be like illustrator. Just something simple like the rest of the things fabric can do. Get in do your thing and get out.
This is your point of view @sideburn, and is a fully respectable point of view.
I work hard for fabricJS and i do not have any fun or gain from supporting the tshirt editor community. Those are commercial websites that can afford to pay a web-developer to get their simple thing done.
Outside the time and resource constrains of a work environment, i do this for passion, and either i do it good and with an api that makes sense, or i do not do it.
A bend text feature does not make sense for me.
There is also an implementation for the 1.x branch somewhere that works, and people can just take it.
Oh Sorry I wasnāt trying to say that I expected you to add it or that I was expecting anything more from you. Just my thoughts as to why so many people are looking for that type of thing. Any new features that you want to put in it would be awesome. Itās great the way it is. Iām impressed! The little app I picked up did their own text bend but it broke in v1.7.22 so instead of me trying to fix it I went looking for another solution that someone else has done but I havenāt had any luck finding one that will work the way I need it to. I will get it sorted out eventually. This project is so old it doesnāt even work with v2.0 so I have to stick with 1.x. At least for now. And I agree if people profit from it they should donate!
My point was only that if outside of work, we do the quick thing to make people request happy quality metrics will go down inevitably.
We need to aim at the professional result, and get the best we can get.
Agreed.
@av01d That's a nice implementation you have. I used your fiddle to add curvetext to my website. My only issue so far is that the resolution on smaller text objects is not quite good enough.
This is being used for a print/sticker shop, and if the user order large stickers, with fairly small curved text, the print looks a bit blurry. Do you know of a quick fix to increase the resolution of the text?
@sweetsmurph: It's not only the text that looks blurry then, I presume? The (curved) text is rendered on a "default" FabricJS canvas, as usual. Maybe you're using this to only render curved text, nothing else? In that case: enlarge your FabricJS canvas, and render the curved text larger.
In other words: I don't think your question is related to curved text specifically.
You might want to try enabling retina scaling: http://fabricjs.com/docs/fabric.Canvas.html#enableRetinaScaling
@av01d Retina scaling is set to true.
So it's a little bit strange. I created an example you can look at from the site:
https://www.markmaster.com/en/labels/stickers?id=116585&dvos=1
Here I got one normal fabric text object, and one curved created by implementing the fiddle you made.
I set the size of the sticker to our max (30cm x 30cm, because it's on larger stickers this issue happens).
It might be difficult to see the difference (how the curved text is more blurry here), but in production file, it's very noticeable.
PDF of stciker (production file):
https://www.docdroid.net/Slr6jVK/116585.pdf
The production file is created by creating an image of the canvas, and then placing that image in an PDF document.
Any thoughts?
@sweetsmurph I'm not sure how to help. I need to be able to look at your exact code to determine what could be done to improve the quality. The issue might be in how you convert your canvas to an image, then to PDF, or it might indeed be in my code.
If you could make a fiddle of your issue, I might be able to help.
@av01d Is there a way I can contact you so we don't high jack this thread?
@sweetsmurph arjan at avoid dot org
Is this solved?
What is missing?
@lucasa: Check https://jsfiddle.net/av01d/4p0syzw3/
It's a solution that works for me. Check whether it's what you need.
Thanks for making this, It works well :)
@av01d same thing happens to me as @sweetsmurph
If you export the canvas with a multiplier which is common for printing the text is rendered at the original pixel size not the scale up size.
I believe for normal text this is handled internally by fabric by setting a scale on the canvas but since your solution draws to a canvas which is then multiplied x times by canvas it comes out blurry.
This could probably be solved by drawing onto the ctx supplied in _render directly. I can't see why it's rendering onto a temporary canvas but guessing it's a kinda lazy way of not having to know where exactly we are drawing too. I can't can't quite work it out.
Would appreciate if you could take a look @av01d
Here's a fiddle with the multiplied document writing out to the body so scroll down a lot as you're looking at a lot bigger image. Notice normal text isn't blurry but your curved text is.
https://jsfiddle.net/mjpch7uz/
On a side note: A preferred curve text class would really involve extending text so all the standard properties can be used but seeing this issue has been open for 5 years I'll take yours š
@shokimble: Here's an updated fiddle: http://jsfiddle.net/av01d/5vcmx9pt/
On line 225 you can set a zoomfactor.
I am rendering on a temp. canvas, because of the fact that I first draw a circle (which can be huge), then I draw the text along that circle, then I trim the temp. canvas (remove all transparent pixels surrounding the text). I don't know (yet) how to only draw text-along-circle without having to trim.
The default for zoomFactor is 1 (unsharp), you can increase this as needed.
This works wonders... but you might run out of memory when the curved text is drawn with a large radius.
In order to draw the curved text, I need to have a canvas that's as large as the radius the curved text is gonna have.
For example: for a 500px radius, when the zoomFactor is 2, this resulting temporary canvas is 1000px x 1000px. This adds up very quickly when the radius grows. Depending on your browser, you will eventually run out of memory.
Thanks for writing that up.
Understand the concerns about memory as the radius can get very large.
The problem I have and I'm sure others will too is you may not actually know what the multiplier is ahead of time.
I think the issue you described might be a non issue as you can extend beyond the canvas and go into negative coords without an error occuring.
I'll have a play with it and report back.
Thanks again
I tried to make a solution.
check it out... https://youtu.be/fnmhQVSJ2jg
Sorry for bad quality of the video.
@mahmudz Looks promising, very well done! Will you share your code, as I did, when you think it's ready?
i won't accept solutions that do not cover text on path and from svg to svg export.
Curved text is less generic than text on a path and less powerfull.
I understand is a nice feature, but not worth alone.
CleverBrush (https://cleverbrush.com/editor/) managed to implement it: text-on-path with SVG-export.
I think the SVG-part is done on the server though. It's not open source....
svg export is very easy, is the canvas rendering that i think is not. There is another lib that support text on path and i think is called paper.js?
In reference of below fiddle :
https://jsfiddle.net/av01d/4p0syzw3/
There is one issue that when we scale arc text with 0 width and height, at that time it will fire error in console line about getImageData
Is there any solution for prevent user to make scaling till minimum 100px or any patch for text not overlap when user scale down that circular text (prevent user to scale down when both end of text are touch up with each other)
Please help if possible and update fiddle.
Is there a solution to work on Node ?
Here is an old curved class created on Fabricjs 1.X that worked fine.
It is not possible to correcte it to work on Fabric 3.x ?
`(function (global){
"use strict";
var fabric=global.fabric||(global.fabric={}),
extend=fabric.util.object.extend,
clone=fabric.util.object.clone;
if(fabric.CurvedText){
fabric.warn('fabric.CurvedText is already defined');
return;
}
var stateProperties=fabric.Text.prototype.stateProperties.concat();
stateProperties.push(
'radius',
'spacing',
'reverse',
'effect',
'range',
'largeFont',
'smallFont',
'globalCompositeOperation'
);
var _dimensionAffectingProps=fabric.Text.prototype._dimensionAffectingProps;
_dimensionAffectingProps['radius']=true;
_dimensionAffectingProps['spacing']=true;
_dimensionAffectingProps['reverse']=true;
_dimensionAffectingProps['fill']=true;
_dimensionAffectingProps['effect']=true;
_dimensionAffectingProps['width']=true;
_dimensionAffectingProps['height']=true;
_dimensionAffectingProps['range']=true;
_dimensionAffectingProps['fontSize']=true;
_dimensionAffectingProps['shadow']=true;
_dimensionAffectingProps['largeFont']=true;
_dimensionAffectingProps['smallFont']=true;
_dimensionAffectingProps['globalCompositeOperation']=true;
var delegatedProperties=fabric.Group.prototype.delegatedProperties;
delegatedProperties['backgroundColor']=true;
delegatedProperties['textBackgroundColor']=true;
delegatedProperties['textDecoration']=true;
delegatedProperties['stroke']=true;
delegatedProperties['strokeWidth']=true;
delegatedProperties['shadow']=true;
delegatedProperties['fontWeight']=true;
delegatedProperties['fontStyle']=true;
delegatedProperties['strokeWidth']=true;
delegatedProperties['textAlign']=true;
delegatedProperties['opacity']=true;
delegatedProperties['globalCompositeOperation']=true;
/**
* Group class
* @class fabric.CurvedText
* @extends fabric.Text
* @mixes fabric.Collection
*/
fabric.CurvedText=fabric.util.createClass(fabric.Text, fabric.Collection, /** @lends fabric.CurvedText.prototype */ {
/**
* Type of an object
* @type String
* @default
*/
type: 'curvedText',
/**
* The radius of the curved Text
* @type Number
* @default 50
*/
radius: 50,
/**
* Special Effects, Thanks to fahadnabbasi
* https://github.com/EffEPi/fabric.curvedText/issues/9
*/
range: 5,
smallFont: 10,
largeFont: 30,
effect: 'curved',
/**
* Spacing between the letters
* @type fabricNumber
* @default 20
*/
spacing: 20,
// letters: null,
/**
* Reversing the radius (position of the original point)
* @type Boolean
* @default false
*/
reverse: false,
/**
* List of properties to consider when checking if state of an object is changed ({@link fabric.Object#hasStateChanged})
* as well as for history (undo/redo) purposes
* @type Array
*/
stateProperties: stateProperties,
/**
* Properties that are delegated to group objects when reading/writing
* @param {Object} delegatedProperties
*/
delegatedProperties: delegatedProperties,
/**
* Properties which when set cause object to change dimensions
* @type Object
* @private
*/
_dimensionAffectingProps: _dimensionAffectingProps,
/**
*
* Rendering, is we are rendering and another rendering call is passed, then stop rendering the old and
* rendering the new (trying to speed things up)
*/
_isRendering: 0,
/**
* Added complexity
*/
complexity: function (){
this.callSuper('complexity');
},
initialize: function (text, options){
options||(options={});
this.letters=new fabric.Group([], {
selectable: false,
padding: 0
});
this.__skipDimension=true;
this.setOptions(options);
this.__skipDimension=false;
if(parseFloat(fabric.version) >= 2) {
this.callSuper('initialize', text, options);
}
this.setText(text);
this._render();
},
setText: function (text){
if(this.letters){
while(text.length!==0&&this.letters.size()>=text.length){
this.letters.remove(this.letters.item(this.letters.size()-1));
}
for(var i=0; i<text.length; i++){
//I need to pass the options from the main options
if(this.letters.item(i)===undefined){
this.letters.add(new fabric.Text(text[i]));
}else{
this.letters.item(i).setText(text[i]);
}
}
}
this.callSuper('setText', text);
this._render();
},
_initDimensions: function (ctx){
// from fabric.Text.prototype._initDimensions
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
if(this.__skipDimension){
return;
}
if(!ctx){
ctx=fabric.util.createCanvasElement().getContext('2d');
this._setTextStyles(ctx);
}
this._textLines=this.text.split(this._reNewline);
this._clearCache();
var currentTextAlign=this.textAlign;
this.textAlign='left';
this.width=this.getWidth();
this.textAlign=currentTextAlign;
this.height=this.getHeight();
//this.set
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
this._render(ctx);
},
_render: function (ctx){
var renderingCode=fabric.util.getRandomInt(100, 999);
this._isRendering=renderingCode;
if(this.letters){
var curAngle=0,
curAngleRotation=0,
angleRadians=0,
align=0,
textWidth=0,
space=parseInt(this.spacing),
fixedLetterAngle=0;
//get text width
if(this.effect==='curved'){
for(var i=0, len=this.text.length; i<len; i++){
textWidth+=this.letters.item(i).width+space;
}
textWidth-=space;
}else if(this.effect==='arc'){
fixedLetterAngle=((this.letters.item(0).fontSize+space)/this.radius)/(Math.PI/180);
textWidth=((this.text.length+1)*(this.letters.item(0).fontSize+space));
}
// Text align
if(this.get('textAlign')==='right'){
curAngle=90-(((textWidth/2)/this.radius)/(Math.PI/180));
}else if(this.get('textAlign')==='left'){
curAngle=-90-(((textWidth/2)/this.radius)/(Math.PI/180));
}else{
curAngle=-(((textWidth/2)/this.radius)/(Math.PI/180));
}
if(this.reverse)
curAngle=-curAngle;
var width=0,
multiplier=this.reverse?-1:1,
thisLetterAngle=0,
lastLetterAngle=0;
for(var i=0, len=this.text.length; i<len; i++){
if(renderingCode!==this._isRendering)
return;
for(var key in this.delegatedProperties){
this.letters.item(i).set(key, this.get(key));
}
this.letters.item(i).set('left', (width));
this.letters.item(i).set('top', (0));
this.letters.item(i).setAngle(0);
this.letters.item(i).set('padding', 0);
if(this.effect==='curved'){
thisLetterAngle=((this.letters.item(i).width+space)/this.radius)/(Math.PI/180);
curAngle=multiplier*((multiplier*curAngle)+lastLetterAngle);
angleRadians=curAngle*(Math.PI/180);
lastLetterAngle=thisLetterAngle;
this.letters.item(i).setAngle(curAngle);
this.letters.item(i).set('top', multiplier*-1*(Math.cos(angleRadians)*this.radius));
this.letters.item(i).set('left', multiplier*(Math.sin(angleRadians)*this.radius));
this.letters.item(i).set('padding', 0);
this.letters.item(i).set('selectable', false);
}else if(this.effect==='arc'){//arc
curAngle=multiplier*((multiplier*curAngle)+fixedLetterAngle);
angleRadians=curAngle*(Math.PI/180);
this.letters.item(i).set('top', multiplier*-1*(Math.cos(angleRadians)*this.radius));
this.letters.item(i).set('left', multiplier*(Math.sin(angleRadians)*this.radius));
this.letters.item(i).set('padding', 0);
this.letters.item(i).set('selectable', false);
}else if(this.effect==='STRAIGHT'){//STRAIGHT
//var newfont=(i*5)+15;
//this.letters.item(i).set('fontSize',(newfont));
this.letters.item(i).set('left', (width));
this.letters.item(i).set('top', (0));
this.letters.item(i).setAngle(0);
width+=this.letters.item(i).get('width');
this.letters.item(i).set('padding', 0);
this.letters.item(i).set({
borderColor: 'red',
cornerColor: 'green',
cornerSize: 6,
transparentCorners: false
});
this.letters.item(i).set('selectable', false);
}else if(this.effect==='smallToLarge'){//smallToLarge
var small=parseInt(this.smallFont);
var large=parseInt(this.largeFont);
//var small = 20;
//var large = 75;
var difference=large-small;
var center=Math.ceil(this.text.length/2);
var step=difference/(this.text.length);
var newfont=small+(i*step);
//var newfont=(i*this.smallFont)+15;
this.letters.item(i).set('fontSize', (newfont));
this.letters.item(i).set('left', (width));
width+=this.letters.item(i).get('width');
//this.letters.item(i).set('padding', 0);
/*this.letters.item(i).set({
borderColor: 'red',
cornerColor: 'green',
cornerSize: 6,
transparentCorners: false
});*/
this.letters.item(i).set('padding', 0);
this.letters.item(i).set('selectable', false);
this.letters.item(i).set('top', -1*this.letters.item(i).get('fontSize')+i);
//this.letters.width=width;
//this.letters.height=this.letters.item(i).get('height');
}else if(this.effect==='largeToSmallTop'){//largeToSmallTop
var small=parseInt(this.largeFont);
var large=parseInt(this.smallFont);
//var small = 20;
//var large = 75;
var difference=large-small;
var center=Math.ceil(this.text.length/2);
var step=difference/(this.text.length);
var newfont=small+(i*step);
//var newfont=((this.text.length-i)*this.smallFont)+12;
this.letters.item(i).set('fontSize', (newfont));
this.letters.item(i).set('left', (width));
width+=this.letters.item(i).get('width');
this.letters.item(i).set('padding', 0);
this.letters.item(i).set({
borderColor: 'red',
cornerColor: 'green',
cornerSize: 6,
transparentCorners: false
});
this.letters.item(i).set('padding', 0);
this.letters.item(i).set('selectable', false);
this.letters.item(i).top=-1*this.letters.item(i).get('fontSize')+(i/this.text.length);
}else if(this.effect==='largeToSmallBottom'){
var small=parseInt(this.largeFont);
var large=parseInt(this.smallFont);
//var small = 20;
//var large = 75;
var difference=large-small;
var center=Math.ceil(this.text.length/2);
var step=difference/(this.text.length);
var newfont=small+(i*step);
//var newfont=((this.text.length-i)*this.smallFont)+12;
this.letters.item(i).set('fontSize', (newfont));
this.letters.item(i).set('left', (width));
width+=this.letters.item(i).get('width');
this.letters.item(i).set('padding', 0);
this.letters.item(i).set({
borderColor: 'red',
cornerColor: 'green',
cornerSize: 6,
transparentCorners: false
});
this.letters.item(i).set('padding', 0);
this.letters.item(i).set('selectable', false);
//this.letters.item(i).top =-1* this.letters.item(i).get('fontSize')+newfont-((this.text.length-i))-((this.text.length-i));
this.letters.item(i).top=-1*this.letters.item(i).get('fontSize')-i;
}else if(this.effect==='bulge'){//bulge
var small=parseInt(this.smallFont);
var large=parseInt(this.largeFont);
//var small = 20;
//var large = 75;
var difference=large-small;
var center=Math.ceil(this.text.length/2);
var step=difference/(this.text.length-center);
if(i<center)
var newfont=small+(i*step);
else
var newfont=large-((i-center+1)*step);
this.letters.item(i).set('fontSize', (newfont));
this.letters.item(i).set('left', (width));
width+=this.letters.item(i).get('width');
this.letters.item(i).set('padding', 0);
this.letters.item(i).set('selectable', false);
this.letters.item(i).set('top', -1*this.letters.item(i).get('height')/2);
}
}
var scaleX=this.letters.get('scaleX');
var scaleY=this.letters.get('scaleY');
var angle=this.letters.get('angle');
this.letters.set('scaleX', 1);
this.letters.set('scaleY', 1);
this.letters.set('angle', 0);
// Update group coords
this.letters._calcBounds();
this.letters._updateObjectsCoords();
//this.letters.saveCoords();
// this.letters.render(ctx);
this.letters.set('scaleX', scaleX);
this.letters.set('scaleY', scaleY);
this.letters.set('angle', angle);
this.width=this.letters.width;
this.height=this.letters.height;
this.letters.left=-(this.letters.width/2);
this.letters.top=-(this.letters.height/2);
// console.log('End rendering')
}
},
_renderOld: function (ctx){
if(this.letters){
var curAngle=0,
angleRadians=0,
align=0;
// Text align
var rev=0;
if(this.reverse){
rev=0.5;
}
if(this.get('textAlign')==='center'||this.get('textAlign')==='justify'){
align=(this.spacing/2)(this.text.length-rev); // Remove '-1' after this.text.length for proper angle rendering
}else if(this.get('textAlign')==='right'){
align=(this.spacing)(this.text.length-rev); // Remove '-1' after this.text.length for proper angle rendering
}
var multiplier=this.reverse?1:-1;
for(var i=0, len=this.text.length; i
curAngle=multiplier(-iparseInt(this.spacing, 10)+align);
angleRadians=curAngle(Math.PI/180);
for(var key in this.delegatedProperties){
this.letters.item(i).set(key, this.get(key));
}
this.letters.item(i).set('top', (multiplier-Math.cos(angleRadians)*this.radius));
this.letters.item(i).set('left', (multiplier+Math.sin(angleRadians)*this.radius));
this.letters.item(i).setAngle(curAngle);
this.letters.item(i).set('padding', 0);
this.letters.item(i).set('selectable', false);
}
// Update group coords
this.letters._calcBounds();
if(this.reverse){
this.letters.top=this.letters.top-this.height*2.5;
}else{
this.letters.top=0;
}
this.letters.left=this.letters.left-this.width/2; // Change here, for proper group display
//this.letters._updateObjectsCoords(); // Commented off this line for group misplacement
this.letters.saveCoords();
// this.letters.render(ctx);
this.width=this.letters.width;
this.height=this.letters.height;
this.letters.left=-(this.letters.width/2);
this.letters.top=-(this.letters.height/2);
}
},
render: function (ctx, noTransform){
// do not render if object is not visible
if(!this.visible)
return;
if(!this.letters)
return;
ctx.save();
this.transform(ctx);
var groupScaleFactor=Math.max(this.scaleX, this.scaleY);
this.clipTo&&fabric.util.clipContext(this, ctx);
//The array is now sorted in order of highest first, so start from end.
for(var i=0, len=this.letters.size(); i<len; i++){
var object=this.letters.item(i),
originalScaleFactor=object.borderScaleFactor,
originalHasRotatingPoint=object.hasRotatingPoint;
// do not render if object is not visible
if(!object.visible)
continue;
// object.borderScaleFactor=groupScaleFactor;
// object.hasRotatingPoint=false;
object.render(ctx);
// object.borderScaleFactor=originalScaleFactor;
// object.hasRotatingPoint=originalHasRotatingPoint;
}
this.clipTo&&ctx.restore();
//Those lines causes double borders.. not sure why
// if(!noTransform&&this.active){
// this.drawBorders(ctx);
// this.drawControls(ctx);
// }
ctx.restore();
this.setCoords();
},
/**
* @private
*/
_set: function (key, value){
this.callSuper('_set', key, value);
if(this.letters){
this.letters.set(key, value);
//Properties are delegated with the object is rendered
// if (key in this.delegatedProperties) {
// var i = this.letters.size();
// while (i--) {
// this.letters.item(i).set(key, value);
// }
// }
if(key in this._dimensionAffectingProps){
this._initDimensions();
this.setCoords();
}
}
},
toObject: function (propertiesToInclude){
var object = extend(this.callSuper('toObject', propertiesToInclude), {
radius: this.radius,
spacing: this.spacing,
reverse: this.reverse,
effect: this.effect,
range: this.range,
smallFont: this.smallFont,
largeFont: this.largeFont
//letters: this.letters //No need to pass this, the letters are recreated on the fly every time when initiated
});
if(!this.includeDefaultValues){
this._removeDefaultValues(object);
}
return object;
},
/**
* Returns string represenation of a group
* @return {String}
*/
toString: function (){
return '#<fabric.CurvedText ('+this.complexity()+'): { "text": "'+this.text+'", "fontFamily": "'+this.fontFamily+'", "radius": "'+this.radius+'", "spacing": "'+this.spacing+'", "reverse": "'+this.reverse+'" }>';
},
/* _TO_SVG_START_ */
/**
* Returns svg representation of an instance
* @param {Function} [reviver] Method for further parsing of svg representation.
* @return {String} svg representation of an instance
*/
toSVG: function (reviver){
var markup=[
'<g ',
'transform="', this.getSvgTransform(),
'">'
];
if(this.letters){
for(var i=0, len=this.letters.size(); i<len; i++){
markup.push(this.letters.item(i).toSVG(reviver));
}
}
markup.push('</g>');
return reviver?reviver(markup.join('')):markup.join('');
}
/* _TO_SVG_END_ */
});
/**
* Returns {@link fabric.CurvedText} instance from an object representation
* @static
* @memberOf fabric.CurvedText
* @param {Object} object Object to create a group from
* @param {Object} [options] Options object
* @return {fabric.CurvedText} An instance of fabric.CurvedText
*/
fabric.CurvedText.fromObject=function (object){
return new fabric.CurvedText(object.text, clone(object));
};
fabric.util.createAccessors(fabric.CurvedText);
/**
* Indicates that instances of this type are async
* @static
* @memberOf fabric.CurvedText
* @type Boolean
* @default
*/
fabric.CurvedText.async=false;
})(typeof exports!=='undefined'?exports:this);`
Hi @asturur Any update on this?
Hi @asturur Would you please confirm by when you are planning to launch updated curved text JS?
Hello, I am also looking for this update
I am also eager for an update
Bountysource decided to update their Terms of Service:
2.13 Bounty Time-Out.
If no Solution is accepted within two years after a Bounty is posted, then the Bounty will be withdrawn and the amount posted for the Bounty will be retained by Bountysource. For Bounties posted before June 30, 2018, the Backer may redeploy their Bounty to a new Issue by contacting [email protected] before July 1, 2020. If the Backer does not redeploy their Bounty by the deadline, the Bounty will be withdrawn and the amount posted for the Bounty will be retained by Bountysource.
https://www.bountysource.com/issues/446987-curve-text-feature
thanks @gustavorps i ll try to save the bounty
I also hope to update the arc text soon
@lucasa: Check https://jsfiddle.net/av01d/4p0syzw3/
It's a solution that works for me. Check whether it's what you need.
SVG export not working :(
@rifatwahid sit tight, official support for textpath is currently in the works.
@rifatwahid sit tight, official support for textpath is currently in the works.
@melchiar I have configured the code (https://jsfiddle.net/av01d/4p0syzw3/) in a test project but couldn't make SVG export work :( is it possible to help me with the SVG export?
I have tried with fabricjs 3.6.3 and 4.0.0 as well
@rifatwahid Sorry, I'm not able to help you add SVG support. The solution you're using was built by @av01d so you could perhaps reach out to him for help. I'd advise waiting though and using the official text on a path solution when it's ready, which will support SVG import/export as well as the ability to curve text along any arbitrary path, not just circles.
@melchiar thank you so much for the reply :) any expected or idea about the release date? :)
@rifatwahid it will be released when it's ready š
@melchiar I can't sleep for this :D hope it will be released soon. Can I get this feature here: https://github.com/fabricjs/fabric.js/releases/tag/v4.0.0 ?
Thank you so much for making this excellent canvas library š š
official progress here:
https://github.com/fabricjs/fabric.js/pull/6543
Most helpful comment
I think I have a nice solution for everyone:
A real fabricjs object for curved/circular text. Note: this is not text-along-path, this is text-along-circle. It works in fabricjs-1.7.x and in 2.x.
https://jsfiddle.net/av01d/4p0syzw3/
For fabricjs-2.x, some very small changes might be needed, contact me if you can't get it to work.