Text Plane Module threejs example
I am always thinking in terms of what more I can do when it comes to making javaScript modules built on top of threejs that I can use in my various video projects that I make for these blog posts. One such idea is to make an improved way to go about adding text content to a scene object as I am not happy with my current solution for doing so. There are a number of ways of doing this sort of thing I am sure, but I was thinking in terms of making a module centered around the idea of having one or more mesh objects that use a plane geometry and canvas textures as a way of displaying text content in a scene.
The process of doing this sort of thing will then prove to be a little involved then. On top of the text plane module itself I will also want to have at least some kind of canvas module such as the one that I made for my post on canvas textures. With that said because I want to just get up and running with the text plane module I will have to just go with what I worked out when it comes to that sort of thunk so far and get to work on the text plane module. However speaking of the text plane module there is a lot that I will need to do with text, such as End of Line conversion, wrapping text, and using the various 2d canvas drawing methods to render that text to a canvas element.
This will then be yet another one of my threejs examples where I am writing about a module or some kind of project that is built on top threejs. This time it will have a lot to do with using canvas elements to create textures, and also a whole lot about working with text content.
The text Plane threejs module example and what to know first
This is a post in which I am writing about the state of a javaScript module that I made that creates textures from text content using canvas elements that can then be used to skin a plane geometry. This is then a little bit of an advanced project type post in which I am assuming that you all ready have a fair amount of background with threejs and client side javaScript in general. Also this is not at all a getting started type post with canvas elements as well so I assume that you have at least a little background working with those elements as well.
read up more on canvas and data textures
In this post I am making use of canvas textures as a way to display text with the plane geometry of a mesh object. There is a lot to cover when it comes to just getting started with canvas elements alone, as well as using canvas elements to create textures in threejs. There are also other ways of creating textures with javaScript code in threejs such as data textures which allow for creating textures with raw color data.
source code is up on Github
The source code for the text plane module, the canvas module I am working on top of, as well as all the demos can be found in my test threejs repository on Github.
version numbers matter
When I first started this example I was using r140 of threejs.
1 - The first version of the text plane module ( r0 ) as well as r1 of of my canvas module, and demos
In this section I am writing about r0 of the text plane module where I manage to all ready get the core idea of what I wanted working which is great. The module allows for me to quickly create a mesh object with the plane geometry constructor and the basic material with the map option set to the current state of a canvas texture that I can update as needed. I can then create an array of text lines from a raw text source, and then use that with an update lines method to have scrolling text in a canvas element that I can then use to create and update a texture that is used with the plane geometry.
On top of writing about the text plane module itself, I will also want to write about the canvas module that I am working on top of as well as at least one of not more demos.
1.A - The canvas module ( r1 )
I am using r1 of my canvas module that I write about in greater detail in my blog post on canvas textures. The main thing about this module is to just have a way to abstract away methods that I use to draw to the 2d context away into a module. There are two built in examples of this in the module itself with the square and rnd built in methods. However I did not want to go nuts with built in draw methods as much of that will be customized in the various additional modules that I will make that will work on top of this, such a the text plane module that this blog post is all about.
The two main public methods here are the create method, and the update method. The create method will create and return a new canvas object that will contain a reference to a canvas element, a 2d drawing context and also one or two textures depending on the update mode. You see I am a little torn between using canvas textures and data textures when it comes to creating texture with JavaScript code rather than external image assets. So I made this module in such a way that I can just update a canvas texture, or both a canvas texture and a data texture. Doing both is expensive so that is why I have update modes where if I am in a situation in which canvas alone is fine I can just update the canvas texture only and save overhead.
|
|
1.B - The text Plane Module ( r0 )
Now for the text plane module that I can use to create a canvas object with the canvas module and use that as a way to update the textures that I can use for the map option of the material that I use for a mesh that uses the plane geometry. There is a lot to wrote about with this module in terms of both private helper functions as well as the current set of public methods that I will be using when making one or more demos, as well as actual projects that will make use of this module.
At the top of the module I have a few private helper functions that I am using, one of which is a warp text method that is based off what what I have from my blog post on regular expressions, which in turn was based on what i found at stack overflow here. This warp text method works somewhat okay, but with one little problem that has to do with really long words that might go beyond the max width that I want. I found a way to deal with that in my create text lines public method that I will be getting to a little later here.
Yet another concern that I have when dealing with text is that often I will be dealing with text content with a mix of End of Line patterns that are used. That is that often I will have content that will use the windows patter, and then others that will use the Unit pattern. Also often I have text content that is a mix of the two actually and this is in part because I am a bit of a Windows and Linux kind of person what keeps switching between different editors and I do not always do the best job converting end of line patterns. This is not such a big deal if I just have a little helper function that will convert all of these patterns to just one standard before splitting the text into an array of strings and that is what my End of line Convert helper function is all about.
Another helper that I have is a vanilla javaScript alternative to the lodash chunk method, in fact the method is copied from my post on that subject. This is a method that I am also using in my create text lines public methods to help address that problem with long words not wrapping.
The create lines helper is what I call once to create a fixed set of objects that I update as needed in order to display text content. The smooth y helper is the method that i use to update these lines to display a long volume of text. I then also have the built in draw function that I use for the draw option when creating the canvas object with my canvas javaScript module that I wrote about above. That about covers all the private helper functions now I just need to wrote a thing or two about the public methods of this thing.
|
|
The create canvas object method is what will call the create method of my canvas module to create the object that is returned that contains references to a canvas element as well as everything else that is included in such an object such as the state object that will hold the line objects used for rendering text to the canvas. This create canvas object public function is what I will want to call directly if I want to create a canvas object by itself to use with something other than a plane. For example say that I want to use the texture property of the canvas object to use as a texture for the background of a whole scene. I can create just the texture object with this method and then set the value of scene.background to the texture.
I then have a create plane method that will create a canvas object and append that to the user data object of the mesh object, and a mesh object will be what is returned by this. This allows be to quickly create and set up a mesh object complete with the canvas object, geometry, and a material with the map value set to the texture or data texture property of the canvas object depending on the update mode.
The create text lines public method is what I will want to call in order to convert plain old text into an array of sub strings that can then work well with the line objects of the state object of the canvas object.
I then also have a move lines method that is what I am current using to update the state of the lines of the state object of the canvas object.
1.1 - First demo of the text plane module ( r0 )
Now that I wrote about the canvas and text plane modules I will now want to have at least one if not more demos of this for the sake of making sure that it is working the way that I would like it to. For this demo the aim is not to do anything fancy I will just want to create a mesh object with the canvas object, plane, and material all set up for my by calling that create plane method. I will then just want to create an array of text lines to use with it and the use that array of text lines with the move lines method in an update loop.
|
|
So far so good, it would seem that I have the general idea of what I would like working. Now I might want to test out at least a few more things before moving on to making my next revision of this module. There is the idea of testing this out with other mesh objects, as well as doing things like mutating the position attribute of a plane and a whole bunch of other things.
1.2 - Using a Sphere by calling the create canvas object method rather than create plane
When I make a module like this often I will just have a create method and an update method, however for this module I know that I am going to want to have at least two create methods. There is the create plane method that will create and return a mesh object with everything set up for me and ready to go. However what if I want to try a mesh object with the sphere Geometry rather than plane geometry, or what if I want to use the canvas texture with some other material or map of a material? That is then why I have the create canvas method as an alternative to just always calling the create plane method.
Here in this example I am creating just the canvas object and then using it with a mesh object in which I am using a sphere geometry rather than that of plane geometry.
|
|
1.3 - Using a custom draw method for one or more new canvas objects
One major thing that I would like to do is to not just have text moving over a solid color background, but over some other kind of texture. This could be the texture that is all ready used for a model or texture that I create with other canvas objects as I am doing here.
The generate idea is to create a canvas object with the text plane module, but use it to just update the canvas element and use that canvas element with the draw image method of the 2d context of other canvas elements. I then use a final canvas element that uses textures from a canvas that is used to create a background, and then the texture that is used for text to draw over it. This final canvas element is then what I will use to create and update a texture that in turn is used for the map property of a material of a mesh object.
|
|
1.4 - One last r0 demo of the plane text module that has to do with mutation of plane geometry
One last demo of r0 of the plane texture module threejs example until I get around to making an r1 of the module I think. This time I will be making an example that not only uses the text plane module, but also involves some additional code that will mutate the position attribute of the geometry of the mesh that I am using the canvas object with. You see as of r0 I do not have any options for setting the width and height segment counts when it comes to using the create plane method. In future revisions I thing I will be changing that and adding options for that. One major reason why is because I think I will like to make this module not just update the state of a texture to use with the map option of a material use with the mesh object, but also update the state of buffer attribute values such as the position attribute.
In future revisions I have plans to make a more advanced system where I do not just make use of a built in draw function for updating texture, but also make use of built in code that has to do with mutation of geometry also. However for now I have to just do these sorts of things by making one or more helper function in example code that will be the first steps in the direction of making one or more options for update geometry as well as material of a plane.
|
|
The main function of interest with this example would then be the update plane geo position helper which is what I have together thus far when it comes to this sort of thing. For this example alone I wanted to create some kind of effect that involves sin waves, and I am more or less happy with what I have here thus far. However I would need to refine this more when it comes to the expression and options used. When done I think that this will be just one of many built in options for mutation of geometry over time.
Conclusion
I will want to make at least one if not more revisions of this module, but even if I do not get around to it I think I have the general idea that I had in mind working all ready. i just simply wanted to have a way to take some text, create an array of sub strings that are formatted to fix into the size of a canvas element, and then also have a way to scroll that content and all ready I am able to do just that.
I have some ideas for future revisions of this module of course, and if you really want to find out what that is there is checking gout the todo lost in the Github folder. I might however in time might even want to work out yet even another system based off of what I have worked out here, but with 3d text rather than plane geometry and canvas elements. However that would be a better for a whole other post and project if I ever get around to that one.