Our development partners approached us with an idea for a tool that would allow anyone to easily find and customize illustrations according to their needs without any special software or knowledge. Their vision was that ITG would be an Illustration Platform enabling users to automatically create custom illustrations from predefined elements.Online builders are one of the most complex technical domains. They master a large number of state combinations and should provide a stellar performance. In our practice, we have already had experience building online constructors: based on vector graphics (Bitmap, Vector, Canvas manipulation) and even website builders. Goal: to build a customizable online image builder from the ground up, where the user can automatically generate custom illustrations upon request.
While developing this service, we encountered some technical challenges.
Each illustration created with our builder-to-be is, at its core, a complicated SVG composition. This composition contains even smaller SVG components that encompass even smaller elements, and so forth. There is no way of knowing beforehand how detailed and complicated an illustration will be. That means we can not limit the number of nested SVG components in any way.
Our first challenge presented itself as follows: how can we create an illustration builder that will allow the users maximum freedom while keeping the interface simple and easy to use? The challenge was both a UI/UХ challenge and an engineering one. We needed to find a way to manipulate many SVG elements in the most reactive way possible without any speed loss.
Our engineering team found a solution that required all illustrations to have a machine-readable representation that answers to the same unified rules. It was necessary to dynamically develop the builder’s interface depending on the complexity of the illustrations. Having developed a JSON format for presenting images with properties compatible with Sketch export and making it follow a particular set of rules, we created a dynamic UI for our illustration builder. The user interface now allowed the freedom to change different parts of illustrations, switching them to other components and recoloring separate elements in a particular way the user requested.
A separate non-trivial technical task our development team faced was compliance with sizes, offsets, and the correct placement of elements relative to each other and the composition itself.
To solve this issue, we had to resort to an experimental attribute of influence in Sketch’s export on the illustration element’s geometry. After dozens of hours of experimentation, our engineers read the documentation and added math and geometry to the mix. And voila! Illustration templates started to look like what designers intended them to.
At the time, the primary tool for modern UI design was Sketch. We had to export our illustrations from Sketch to ITG. But it was not enough to transform the exported file into JSON and trace the image in the builder. We had to organize how to manipulate the JSON illustration’s state. On the one hand, we had to restore the XML/SVG tree from the object to trace it in the builder; on the other hand, we needed to save the current state of the illustration on the server.
Having rethought the demands towards the format of the illustration object, we have created one more iteration of its evolution, after which it started to satisfy both the Sketch export parameters and the file format that the builder itself was counting on. After this, we could perform an end-to-end performance cycle of the illustrations builder for the first time. Our future builder manipulated the illustrations correctly and saved the results on the server under “My illustrations.”
Illustration preview rendering was another challenging task. When we realized the potential number of users and multiplied it by the possible number of illustrations each of them might have, then multiplied that number by the number of events that required resaving the preview, we dismissed the idea of cover image generation. Our developers had to find a way to render previews of each illustration from its JSON representation, on the fly, right in the builder’s front-end.
To make our solution work, we had to make some architectural changes. We separated the preview rendering from the builder and put it in a separate component. Later, we used it to preview illustrations and render them in the illustration builder. To create a faster preview, our engineers simplified the rendering component. The simplification was achieved by dividing the render parameters and the builder states parameters and making them sufficient to the min extent. Implementation of our solution helped speed up the preview process and cut the potential server storage costs.
Along with the development process, another issue with Sketch’s export arose. As it happened, Sketch's out-of-the-box solution did not give an export opportunity for files in a format easily decomposed on the ITG side to turn illustrations into objects necessary for the builder’s configuration.
Being a custom web development agency often pushes us to explore new solutions. Our team quickly got acquainted with new concepts, a week of experiments sprinkled with love for what we do, and that is all we needed to write our plugin for export from Sketch in the required format. To create a plugin, our developers had to do some math, geometry, and experiments to find all the export properties and parameters. As a result, the alternative export through our plugin worked as intended.
As soon as the team of designers received the Sketch export plugin, we encountered a new problem. Designers drew so much content at an incredible speed, and It took too long to export from Sketch. The problem's essence was that an object of each template composition with the multiple mutually exclusive components of each illustration element is a complex object with a significant nesting depth. The recursive bypass of such large objects becomes relatively long when each recursion iteration needs the application of computationally intensive operations.
A couple of experiments and a transition from synchronous operations to asynchronous gave the result - all recursion iterations were happening practically simultaneously. The complicated export object was asynchronously supplemented with the necessary fragments that (where the structure allowed) were emerging parallelly, not successively.
The improved export speed from Sketch increased the number of exported data errors. Here another challenge awaited us as we needed to enhance the export plugin with the necessary validations to help the designers follow the rules they forgot about and lead the number of invalid exports to zero.
Creating a separate validation module helped us solve the problem. We moved the validation state into a separate component and dynamically changed the validation state as we processed JSON representation illustrations. Additionally, we have incorporated the preview of the result straight into Sketch. After all the data validations had successfully ended, we sent an object to the ITG server, and as an answer, we received the preview generated by it and showed it to the designer. The designer then validates the result additionally visually.
It sounds like a relatively simple task, but in reality, it required a series of architectural micro-decisions, which made it easier to reach a usable result and a good UX for the designers.
Another challenge lay in creating a rather tricky landing from the standpoint of interactive animations. Here we were faced with buttons that changed their form when the user hovered over them, complex animations, and even an interactive game incorporated right into the landing. The game featured a dog floating in space following the user’s mouse and bumping into planets that flowed around it and bounced off each other, taking into account the laws of physics.
We applied different approaches to the buttons that had to change shape when a mouse hovered over them. First, we tried to do everything with only the help of CS animations. The results were dry and needed a smoother animation flow to realize the intended design. Also, the website had two different designs that complicated the workflow.
We have tried Lottie, and it worked well. The technology required constant contact with the designer but gave excellent results. Using Lottie, we have animated an interactive mini-story on the website’s landing, including an animated dog whose appearance users can change with just one click.
The website’s throbber was another exciting thing to work on; a simple element became a fun design decision when we turned it into an animated dog and tabs that started the illustration’s animation.
The interactive game with the flying space dog had several iterations. We tried different libraries and engines but could not reach the desired motion that the designer wanted, which did not load the processor up to 100%. In the end, we have found and used Phaser, and the result can speak for itself.
On-scroll animations give all animated features a finished and wholesome feel.
In record time, we've built a working MVP that covers end-to-end scenarios for designers behind the product and end users enjoying it.
A progressive JavaScript web framework, that enables better, faster results with great performance and lower costs.
Give clients the power to get exactly what they asked for, make it easier to evolve APIs over time, and enable powerful developer tools.
Lightweight and efficient, Node.js is perfect for data-intensive real-time applications that run across distributed devices.
Support transactions, search, analytics, and mobile uses while using a common query interface and a data model that developers love.
Lottie is an open-source animation file format that’s tiny, high quality, scriptable, interactive, and can be manipulated at runtime.
Scalable Vector Graphics (SVG) is a web-friendly vector file format. As opposed to pixel-based raster files like JPEGs, vector files store images via mathematical formulas based on points and lines on a grid.
Phaser is a 2D game framework used for making HTML5 games for desktop and mobile.