The Building of thread’d: React, three.js, & p5.js

Shirley Lin
Frontend Weekly
Published in
4 min readJan 31, 2018
A screenshot of the render page from thread’d

For my most recent and most ambitious project yet, I wanted to make an interactive way to create patterns, save them, and then render those patterns onto a 3D model. Here’s the finished product, in case you’d like to poke around. I’d done little demos in preparation for this project using three.js and vanilla Javascript but the biggest hurdle for this project was combining all these elements together with React.

p5.js

Using p5.js with React was a little bit of an adventure. The thing I was most worried about going into this project was letting React handle the lifecycle of the p5js canvas component. I needed to make sure all functions that were associated with the sketches stopped when the component unmounted.

Here’s are a couple of the p5.js sketches I made for thread’d:

size of circles is controlled by scroll input
the landing page for thread’d

To integrate p5.js with React, I ended up using a handy little wrapper called react-p5-wrapper, though I did end up making a small modification to it to allow for easier clean up. You can see my updated wrapper here.

Using the wrapper, it was fairly easy to create p5 sketches, though there were a few tricks to optimize for React. Here are the top things I learned:

React + p5.js

  1. Clean up is NOT easy on a Single Page App. I did some weird things to ensure my sketches stopped when the component unmounted, including passing down a prop as a flag, editing the wrapper, and even editing the p5.js library.
  2. Usually p5.sound and p5.dom is totally possible. It’s always weird when you google something and there aren’t any results for what you’re trying to do. But through a little trial and error, I did manage to use both p5.dom and p5.sound. If you’re interested in implementing, see this and this part of my github repo.
  3. Simplicity is impressive. p5.js is powerful, and I just scratched the surface of it with my implementation. But just by using some circles, rectangles, and interactions, I managed to create customizable and interesting interactive elements.

three.js

While there are a few libraries out there for three.js and React, I ended up using react-three-renderer. It’s a nice little library that simplifies three.js, but it was a little difficult because I wanted to use custom models I created and exported from Blender. I also wanted Orbit Controls, which are not included out of the box with react-three-renderer. Here’s a little demo of what I ended up with:

Orbit Controls! A Blender-exported model!

Before starting thread’d, I had done a sample of importing the model and rendering the texture from a url in vanilla Javascript and the regular three.js library, so I felt confident I could replicate it with React. Of course, things are always easier in your head. Here are the top things I learned:

React + three.js

  1. Async and Component Lifecycle Methods Matter. One bug that I ran into early on was handling the loading of the model, texture, and setting up orbit controls. I had all of these things happening in componentDidMount(), but my scene wouldn’t render without both the texture and model loaded in. The controls, though, would error out if the scene was not loaded.
  2. Your first try may not be the final solution. I tried hijacking the orbit controls with a setTimeout, which worked (most of the time). If the loaders took extraordinarily long, though, we were stuck. I moved on with other parts of the project, leaving the temporary patch. A few days later, though, with new eyes, I realized the solution! It was simple, really. I chained together the loads — loading the texture after the model loaded, and then setting orbit controls.
  3. Libraries are useful, but not perfect. You will run into many, many situations where your library does not do exactly what you need it to do, or doesn’t include a feature that you want. For instance, react-three-renderer didn’t handle importing models, or orbit controls. I had to come up with creative solutions and defer to vanilla three.js in order to make things works.

Summary

Starting a project is never easy, especially when you’re trying to use many different libraries in conjunction. It’s important to remember that you’re in control, and these libraries are here just to help you. You can modify them, expand them, and make them work for you.

thread’d — an interactive, custom clothing creator

--

--

Shirley Lin
Frontend Weekly

software engineer @codecademy, prev @datacamp, @grailed