Hello! We are a team of ninja-developers of the ninjamock.com project.
Ninjamock.com is another online designer of sketches and prototypes. The project is completely written in javascript and HTML5, the server part is in ASP.NET MVC.
For the year of work on the project, we stepped on a huge number of rakes and have gained invaluable experience in developing large JavaScript applications, which we want to share. In this article we will tell how a prototype from a single index.html file has grown into a full-fledged project with more than 250 classes and 60,000 lines of code (not counting third-party libraries). Also, in general terms, we describe our architecture and describe in detail the implementation of rendering on the client.
UPD: Follow the updates on our twitter or fb page')
Start
We all work (still working) in one large company, and somehow it coincided that we got tired of it at one moment and we decided to
take over the world to start a project that would allow us to work for ourselves. So, one autumn afternoon, we gathered in the bar to drink a mug of "tea" and discuss how to do it. Somewhere after the Nth circle our ingenious plan was ready:
- We write the best sketch designer
- ???
- We make a profit
Later it turned out that we are not original, and this plan came up to us - the
business plan of the dwarfs .
By a sketch designer, we mean an application in which you can draw sketches, wireframes, or mockaps of applications, and also make simple clickable prototypes. Our main target audience is programmers, designers, business analysts and small companies engaged in the development of mobile applications, who need to quickly draw the design of the application, or test a prototype.
We considered the main competitor to the well-known balsamiq.com, whose financial reports inspired us to start working in this area. But it seems that we were not alone who thought the same, and during the year several similar projects appeared.
Unlike balsamiq, which is written in flash, we decided to do everything “correctly” and write in HTML5 so that we could work on all platforms (and because it was a fashion trend at that time).
Another difference from balsamiq is that we focus on specific platforms (iPhone, iPad, Windows Phone, etc.). That is, balsamic is a universal platform for drawing anything, so they do not have semantics specific to specific platforms. Why such semantics is needed? For example, to generate code for the drawn design. With us, all controls behave more or less like real ones.
The current project architecture
The server part is quite simple and implemented on ASP.NET MVC; there is probably nothing to talk about. Most of the code we have is on the client and is written in JavaScript. When we started the project, we looked in the direction of CoffeeScript, but considered that the infrastructure for it at that time was rather raw, so we decided to write everything in pure JavaScript.
Like all JavaScript-respecting developers, we invented more than one bike and wrote several of our frameworks :) For example, we have our own way of creating classes - there are several interesting points that we will discuss in one of the following articles. Now, with the advent of TypeScript, we will most likely switch to it as soon as support appears in WebStorm.
On the client, we have one main page that uses all JavaScript. From third-party frameworks, we use jQuery and knockout.js. However, architecturally we decided not to be tied tightly to third-party frameworks, so we have only a few platform-specific classes in which their use is allowed.
Client code includes:
- The object model of the design elements, i.e., the base classes for our controls.
- The core of the render. This includes mouse and keyboard event handling classes. These classes are responsible for finding and moving elements along the coordinates, drawing up the order of drawing elements, and also calling the drawing itself for each element.
- Design elements (controls) for specific platforms (for now, only for the iPhone). Each control decides for itself how to draw itself in the given coordinates. In the current controls, the drawing of “hardcoded” into the code of the control itself - for example, in the “button” code we draw a rectangle, paint it with a color, then draw the text from the top, align it with the middle, etc. However, to draw new controls (which have not yet been released), we decided to do otherwise - use our own designer to draw full-fledged controls. It turned out quite interesting and we will tell about it in more detail in one of the following articles. Partly this functionality is already available, you can select one or more elements, then right-click and select Assets -> Convert to asset. After that, a new item appears in the left pane. And by double clicking on an element you can edit its template.
- View models (ViewModel) for the page and dialogs. These are platform-independent classes for which knockout.js templates are tied.
- Classes of kernel binding to the platform on which our application is running. Here we have the subscription code for mouse and keyboard events; This code redirects events to the kernel for further processing. For example, on a computer, on an iPad or on an iPhone, subscription to events is done in different ways; Macs and PCs differ in keyboard shortcuts, etc.
- Extensions. When designing our code, we relied on the principle of openness / closeness , so the extensions implemented the functionality that one could do without in principle: for example, snapping elements, highlighting a container when an element is dropped, project autosave in localStorage. We have a total of 17 extensions.
But it all started much easier ...
First prototype
The first prototype was written in a few days. In it, as it should be in the prototype, everything was very simple. Our controls were HTML elements. For example, a rectangle is just a div, the phone's keyboard is img, and the elements are more complicated, where gradients are needed (for example, a tab bar or a toolbar), it is a canvas. All elements had absolute coordinates, the position of elements relative to each other was specified through the css-property z-index. Moving elements has been implemented via jquery.draggable.
All controls were placed in a div element that was our virtual page, i.e., it was wider and taller than the workspace (to allow scrolling), and when scaled, its size changed accordingly.
The main advantages of this approach are the ease of implementation and the excellent scrolling of elements that the browser does for us, well, and many other goodies.
This architecture has existed for several months. But our project grew and developed, and as we added new features, we realized that it did not suit us.
The first stumbling block was the banal zoom, which we could not properly implement. Actually, we had two options:
- CSS zoom - works fine if you need to reduce the element. There is a problem with the increase: all our elements are vector elements, most of them were drawn on canvas. When you increase the canvas through css, its content is scaled raster, while we needed a vector zoom. An example of how this does not work can be found here: jsfiddle.net/MzGpe/3
- “Manual” zoom, when you need to go through all the elements and change their position and size, as well as redraw the entire contents of all the canvas, taking into account the new scale. But we could not achieve a smooth drawing - all the elements jumped awfully (consistently) at the time of scaling.
Surprisingly, none of the competing applications implemented on HTML (fluidui.com, gomockingbird.com, moqups.com) have any scaling.
Second prototype
Our solution was to throw out all the HTML elements and replace them with one big canvas, on which everything was drawn. The size of the canvas was equal to the size of our virtual page. Therefore, scrolling worked as before, but now it is possible to scale everything smoothly.
An additional advantage of this approach is an easy way to generate images from canvas - this allows us to do page thumbnails using the canvas.toDataUrl method. Moreover, all this is done on the client and does not load the server. In addition, we have the opportunity to process individual pixels of the image (which in the future will allow adding interesting graphical tools).
The working area of ​​our application with 15x zoom:

However, everything was not so simple. With any movement of the elements with the mouse (and this is the most frequently used action), the canvas with all controls was redrawn in its entirety, which significantly affected the performance of the application. It was solved quite simply - we added another canvas over the first one. So we got 2 layers (initially there were 3, but that's another story :)). The first layer contained a more or less static picture, which was relatively rarely redrawn, while on the second canvas, temporary objects and various effects were drawn, such as snapping lines and highlighting elements during hover. The result satisfied us almost completely.

However, again there were problems that showed the imperfections of this approach. When scaling, the size of the image, and, accordingly, the size of the canvas, increased. By default, the size of our design page is 1024x768. At 4x magnification, the size of the canvas is 4096x3072, and not every machine can handle drawing (at an acceptable speed). Moreover, on several machines, strange artifacts in the form of stripes and colored dots began to appear on several machines. But a 4-fold increase is far from the limit.
As a result, we came to a decision that we use now. These are the same two canvas, but now their size is not equal to the size of the page design, but to the size of the visible part of the page on the screen. Because of this, we had to abandon the standard scrolling and take into account the position of scrolling when drawing.
With this approach, everything works fine, with the exception of one small minus - the scrolling speed dropped slightly compared with the previous versions.
In the screenshot at the beginning of the article you can see how our project now looks. You can watch it live here:
ninjamock.com .
Epilogue
Now we are actively working to increase the number of controls supported by the platforms (soon there will be support for ipad, windows phone, surface, as well as desktop applications)
and at the same time we are thinking about the second point of our business plan . We will be glad to hear any feedback and answer any questions about our project.
The project team ninjamock - pastorgluk , Denis and
Headwithoutbrains .