Wrestling with Angular and Node.js: Making a Sprite Sheet Maker Web App
Indeed, I’ve finally started work on creating a web app that makes sprite sheets. This project or idea is interfering with the Pantsu Sweeper game’s progress, but that’s okay, because I do more than make video games. I’m finally doing straight-up web development. Also, inefficient time management may be partly to blame.
Initial setup with Node.js
This being a full-stack web app project, I was aware of the issue of juggling the frontend and the backend. Project structure wise, I found that you can simply organize the frontend and backend functionality into seperate directories. The Node.js server would simply display the Angular frontend that’s located in a seperate directory to the user with
dist is the directory where the Angular frontend is compiled by Webpack or whatever magic
angular-cli does when building Angular projects.
What npm packages to choose?
I may have familarity with HTTP server development, but implementing my understanding was difficult at first as I wasn’t aware of what all needed to be implemented. I definitely didn’t want to come up with solutions to web server development that were already solved, so I had to research what Node.js packages would help me execute my vision for this web app.
I discovered that I needed the
cors package to handle Cross-Origin Resource Sharing for uploading files from a browser. For the database storage that I planned for the web app to have, I decided to use MySQL instead of PostgreSQL this time–unlike my first web app of eight months ago–so I included the
mysql package. I’m not sure about needing
body-Parser, which I included.
Multer for uploading files
Multer does a lot for me here. It functions as a middleware for handling the implementation of dealing with files uploaded by the user. I researched how to use it by reading tutorials and the GitHub documentation. I was then able to come up with code that, although not long-lasting as I was focused on quickly reaching a minimum viable product, created the basic architecture of what I wanted to build.
Debugging the API code
For debugging Node.js programs that deal with networking such as APIs, I use Postman. It allows me to fabricate HTTP requests, emulating what a browser would send to a web server. This allowed me to test the API that I was making as there were sure to be mistakes and errors during the creation.
A way for actually creating sprite sheets
Picking node packages that already have solved this problem for me, one particular npm package that I came across,
Buffers for the output of a sprite sheet. I initially thought that having the sprite sheet output being a
Buffer would pose no problem, but I was mistaken as this would become a big problem later on.
spritesmith was a perfect fit for me as it met the requirements for my circumstances. I then decided to use it on the backend and have the output of its work be sent by the API backend to the Angular frontend.
The Angular frontend
angular-cli to initialize the frontend that the user will see.
Reading the official Angular documentation, I found out about template reference variables, which represent a template’s HTML element. The code below passes
filelist.files (which is an HTML5
Filelist’s array of
Files) to the
app-upload-form component’s (which is a web component made for allowing the user to upload files) method member so that the component would not need to know about extra data, as advised in the official Angular documentation.
It was difficult trying to find out how to send HTML5
FormData, as a random person advised not to use. I had to, though, in the end, and using it was actually the correct decision for my circumstances.
I wasted time trying to figure out how to preview the user’s uploaded images in the user’s browser. Though it was a noble feature, I’ll have to rely on using the API server for doing all of the work–was what I thought until I was able to solve the problem of displaying a preview of the sprite sheet image given by the API server.
Solving an image preview problem
My best looking and most technical commit yet involved memory manipulation. It gets rid of something I don’t like the look of and replaces it with something better and simpler.
I believed that I needed a temporary URL (for the image’s
src attribute) to point to the user’s newly created sprite sheet image. The correct implementation for this concept was the creation of an HTML5
Uint8Array using the
Buffer given by the sprite sheet making backend was the solution I was looking for. Only then was I able to create a temporary URL for the new
Blob object. I was joyous when I implemented the solution and was able to finally solve the problem of displaying a preview image of the user’s new sprite sheet.
The above code creates a new
Blob using the image byte data representing the user’s new sprite sheet image retrieved from the API server. The user’s new sprite sheet image is then given a temporary browser URL using
createObjectURL and Angular’s handy
The highlight of the project and the most exciting part, really.
What’s going to happen next?
I’m gonna be hip and trendy and typical right now, and thus say that I learned much so far and had fun. Nonetheless, I’m having trouble right now writing this blog post, struggling to decide whether to use the past tense or the present tense, as I’m considering whether or not to pursue another idea and abandon this one. I’ve always really wanted to make a sprite sheet making web app since I had an issue with making sprite sheets for the Tiled Map Editor while making my 2D platformer game. The goals of this project were to develop a web app, gain more experience with Angular and Node.js, and many other reasons.
I’m not even sure about this being a web app that has a backend server that constantly sends and recieves images–although optimizing the architecture of such a thing is appealing. When I think upon this project, I question whether I should put all functionality on the frontend, in the user’s browser.
If I decide to abandon this project, which is highly likely, I’ll be moving on to new ideas. I won’t really totally abandon it as I may return to it in the far future, like how I returned to my binary search tree inversion project.
Nonetheless, I’m not going to be thinking in absolutes or have bias toward the negatives (I have a unique ultimate vision I want to execute, after all). I’ll instead be aware that I did gain much from this endeavor. I have a new executed idea under my belt. I believe that’s +1 XP gained.