I was thinking about slapping together a quick project that makes use of the Raycaster class to create a simple yet effective menu system in threejs. If you are not familiar with the raycaster constructor in threejs yet, it is something that you will want to look into at some point sooner or layer as it is a very usful tool when it comes to figuring out how to click a mesh object sort of speak. The Raycaster constructor is what can be used to find out if a 2d pointer click of one kind or another has resulted in a mesh object being clicked or not. This raycaster class can be used to find one or more objects from any point in space to another also actually, but for todays threejs project example a raycster instance will help a whole lot if the aim is to make some kind of menu system using threejs.
There are a lot of things that you should know before getting into how to go about making a menu system with three.js. There is of course starting out with a basic getting started type example with threejs if you still have very little experience with threejs first. However regardless of how much experience you may have it might be a good idea to learn more or refresh on a few things so I will be writing about what that is in this intro section of this post.
It might be better to just start out with some very basic hello world type examples with the raycaster class in threejs first. Once one gains a decent grasp on the raycaster class it becomes clear what the various use case examples are for it, and one typical thing to do would be to work out some kind of menu system using it. However I also find it very usful for other tasks as well such as having a way to position a mesh object to the surface of another mesh object and doing so in a way that will work well with just about any kind of geometry.
When I was working on this threejs example last I was using threejs r135, and the code was working well for me at that time with the old example that I started with. The last time I came around to do some editing of this post I started an official r0 of a menu.js module, and with the demos that I started with that I was using r146 of threejs. If the code examples here are not working for you the version of threejs is what you are going to want to check first. After that you might be running into some other kind of problem.
In this section I will be going over r0 of my menu.js file, and at least one if not more demos of the module in action. This is based off of the source code that I started with when I first wrote this post, but with many changes. For one thing I am not leaving the process of setting up the typical objects that have to do with a typical three js project as part of the demo. The create method of the menu module will only create a renderer and so forth if needed in the even that I do not pass one to the create method by way of an options object.
Speaking of the create options I have also added a long of additional basic options that have to do with things like just setting the number of buttons that I want and the size of each button. I did not go to far of the rails with this thus far though as I am not seeing myself using this example in any kind of production project just yet. However if I even do need or want to make some kind of menu system with threejs this might prove to be an okay starting point now.
Here I have the source code for r0 of my menu.js module that seems to work okay thus far. There is just one public method that I call in a project in which I use this that will create and return an object that will contain a group of mesh objects. Each mesh object of the group will be a button that when clicked will fire an on click method and pass a ref to that button mesh object as an argument for the on click method. So then I can set a number of buttons that I want for the menu, and then a custom on click method where I will define the logic that I want to call when a button object is clicked.
This is my first basic demo of r0 of menu.js where I just want to create a few buttons and have the scale of each button change when a button is clicked. So after creating my typical set of objects that I want when making any threejs project I then call the main create method of the menu module. I then use the scene, renderer, and camera objects that I just created for the menu by passing them with the options object when calling the create method. In addition to that I also set the number of buttons that I want for the menu, and define a custom on click method.
The custom on click method that I made for this demo will just set a scale delta value for the button that was clicked to a given amount. This amount will then be used in the process of setting the actual scale value that will be used in an update method. Also in this update method the scale value will reduce over time.
I am then using the object3d traverse method to loop over all the objects of the main group of the menu that is returned. I could use this to do things like set up new materials, and anything else that i would want to change on a mesh by mesh basic. However for the sake of this demo I just want to set up some values for the user data objects of each mesh object.
As of this writing the state of this sm.js is not so great, so things will likely change a whole lot in any future reversions of this examples when I get around to editing this post next. However much of the core functionality that I had in mind is all ready working, so maybe only so much more will need to change.
Now for just a basic hello world style example of this sm module this far. With that said I guess that there is just calling the create sm object method of the module to get my sm object. I will then just need to make sure that I am calling the render method of the object in the body of my main animation loop of the example.
This example alone as well as many of the other simple project examples I have made thus far are in a need of a little more work of course. This is why things have slowed down a little when it comes to writing new posts, this content as well as many others that I have write before need to be revised a little. This whole thing needs to be redone into what I might call a first revision of what I want to have when it comes to this sort of thing, and at the time of this writing I do not have the time yet to do that.
I have poked my head in and edited this content piece a little at this time, but I can not say that this example has a high priority for me when it comes to putting a little more time into it. I have a lot of pots boiling all at once and this project is on a far back burner it at the moment. I seem to me more interested in using threejs as a way to make programs that have to do with making videos, rather than some kind of menu system.
Still when this is up and running the very crude, basic idea, is in fact working. So what needs to happen is just a little refinement of the source code in terms of a standard module type project that I can drop into a folder and link to. There is just a lot more that I would like to add in any and all future revisions of this module that may or may not come to pass if I do ever put more time into this one at some point in the future. Some additional public methods that will help with the process of styling the buttons for one thing maybe.