To celebrate Christmas and our love of Lego in the Pusher office we’ve built a live updating wall of pictures, taken from 500px and using the LegofyJS library to convert them into their lego form. It’s really nice to see a regular stream of christmas lego figures popping up in your browser! We’ve open sourced \[…\]
To celebrate Christmas and our love of Lego in the Pusher office we’ve built a live updating wall of pictures, taken from 500px and using the LegofyJS library to convert them into their lego form. It’s really nice to see a regular stream of christmas lego figures popping up in your browser!
We’ve open sourced the code and put the app live on Heroku and in this post we’ll talk a little bit about some of the tools and techniques we used to build the application.
I’m a big fan of the new features added to JavaScript in ES2015 and take any opportunity to use them in applications today. To do this I used jspm, a package manager for browser side JavaScript applications. I’ve written about jspm previously if you’ve not come across it. This lets us use the majority of ES6 features by running our code through Babel, a code transformer that dutifully converts our ES6 into ES5.
For our first data source we chose 500px. Whilst they don’t provide a realtime API they do provide a fully featured endpoint for searching pictures and have a high enough limit on requests that we are not in danger of getting rate limited.
Rather than directly interface with the 500px API in the browser we decided to build a small server to do this. It will abstract over the 500px API and push updates to our Pusher channel, enabling us to normalise the data before sending down to our client and potentially add data from multiple sources in the future.
To build our near real-time data stream on the server side we make a request to the 500px API every minute, storing the pictures that were retrieved. Each response contains 100 images, and once we filter out the ones we don’t want (we avoid any that 500px mark “nsfw”) we’re usually left with 90+ images. Every three seconds we take one of the stored pictures and use the Pusher Node library to trigger a new_picture
event on a channel called pictures
.
Each request to the 500px API returns more pictures than we need in a minute, so we’re never in danger of running out of data to push through to the browser. This also ensures the user receives a continuous stream of data at reasonable frequency to keep them engaged, but not too fast so that we can maintain a jank free experience. See tools, tips & techniques for building real-time apps for more on these topics.
Remember, all the code is on GitHub, including the code for our server.
Now we’ve got a stream of pictures we can start to generate our lego. Legofy requires the image to be in the DOM, and it will transform it in place, replacing the image with the lego version. Using the PusherJS library we bind to the new_picture
event on the pictures
channel, which is where the server routes its events. We add the image to the DOM twice – one of them will not be changed to lego and the other will. This way we can also add in a hover effect to swap between the two.
Because we’re using ES6, we can take advantage of template strings to make inserting a bit of HTML easier and we also take advantage of jQuery to keep the DOM code more succinct.
Once we’ve taken the HTML and placed them into the DOM we then need to find the image to legofy. Legofy-ing the image is just a case of using legoify on an image in the DOM and specifying a factor
which sets how big each lego block should be. A smaller factor leads to more bricks and hence a higher resolution lego image.
Finally, we’re using the excellent Masonry framework to lay out our pictures in a dynamic grid, that also deals with nicely animating images as they are added (we may have added some snowflakes too).
There’s a slight other complication though; if you’re fetching an image from a remote URL and trying to place it into a canvas you’ll see a rather cryptic error message:
Tainted canvases may not be exported.
The issue here is that the server we’re fetching images from hasn’t enabled Cross Origin Resource Sharing (CORS), and this means we don’t have permission to edit the images and then place them on the page. To get around this we can proxy all requests through our server, which is easily done with the Node request library.
Now the pictures are being served from our own server, so there’s no security issues to worry about.
We hope you enjoy our little lego Christmas extra and if you’d like to get Legofying yourselves, don’t forget that all the source is on GitHub.
We’ve also done some legofying of the Pusher website but you’ll have to search a little harder to find it. If you do find our little Easter/Christmas egg, get in touch and we’ll send you some swag as a reward! Merry Christmas from all of us at Pusher.