Development of a vector editor in JavaScript (difficulties and ideas)

    Background:


    The name is a great experience in the development of websites (about 15 years) and as a programmer, I really do not like routine work, I try either to avoid it or to optimize it in some way. In other words, if at some point I need to deal with content filling the site (yes, I know, not royalit’s up to the programmer to fill the site, but there are different cases), then I would rather spend a couple of hours writing an input data parser than 4 hours manually injecting this data. And for a long time I was tormented by the problem of the lack of a convenient editor for creating image maps. Of course, you can draw a card in Corel Draw or the like, upload it to SVG and quickly convert it to the desired format, but I have long been interested in the possibility of creating some kind of editor that allows, without downloading third-party programs, directly on the site to quickly load an image and select on it the desired card. For example, there is a certain image of a building on which it is necessary to select the floor contour and attach some JavaScript events or just a link to it, like this:




    Also, in addition to manually selecting the outline of the object, I would like to have a tool similar to Magic Wand in Photoshop so that I poke the mouse and you have a ready-made outline. Despite the fact that for several years I have come across various map editors (both on-line and off-line), I did not find a similar function in them. Well, if not, we will write it ourselves.

    I would like to immediately warn, because in the end I found a customer for a commercial product, unfortunately, there will be no full-fledged source code, but I will try to describe the ideas and difficulties that arose during development in as much detail as possible, moreover, I do not specialize in developing graphics and interfaces , so some “revelations” may seem ridiculous or even stupid, however:

    Editor functional definition:


    1. Creating a contour manually, as well as being able to edit previously created contours;
    2. Although the HTML MAP - AREA - SHAPE tag supports several types of shapes for the selected area, it was decided to focus only on creating complex paths using POLY;
    3. Actually, what was interesting to me, as a programmer, was the selection of an area with similar colors, with a single mouse click.

    CANVAS - what is needed?


    Since I already had experience with the CANVAS tag and represented its capabilities, it was decided to dwell on it (as it turned out, this was a mistake that slowed down the development of the editor for a decent time).

    The choice of circuit traversal algorithm:


    After trying several options for loop traversal algorithms, I eventually chose Moor Neighborhood . In my opinion, this algorithm successfully combines the speed of work and the sufficient ease of implementation.

    So: A


    test image for working with a contour.


    Highlighting a contour with straight sides.


    Highlighting a curved contour.

    As you can see, the contour bypass algorithm copes well and selects everything you need, while we see that a relatively small contour requires almost 300 points for straight lines and for some reason, 50 points less if the contour is rotated around its axis.

    In principle, now you can memorize this circuit and work with it, but it is very confusing for a large amount of data, even for a small circuit.

    Optimization of the finished circuit:


    The following scheme for working with the contour was chosen: first, create a contour from points and delete unnecessary ones, with the exception of nodal points (or points of change of direction). On the one hand, there is double work, on the other hand, this scheme simplifies the debugging of the mechanism for removing unnecessary points.

    Selection of nodal points:


    The solution lying on the surface:
    1. We take a point, add it to an array of nodal points (not contour points);
    2. Sequentially go around the points from the starting point, measuring the angular distance between the original and the current, if the angular distance is greater or less than a certain (determined experimentally), then this point is a new starting point, add it to the array \ nodal points;

    This solution works, but the calculation of the angular distance tormented the soul by the presence of "heavy" functions of working with angles. Therefore, it was decided to look at the existing "bicycles" and here is a forgotten solution from school mathematics: a scalar product of vectors .

    We take it as a basis - the algorithm works fine and is many times faster.

    We look at the result:

    13 points - quite satisfied.


    61 points ?! But why?!

    But here’s why: I somehow forgot that, despite the high resolutions of monitors, retins, etc., the line on the screen in fact is a broken set of points (but some 20 years ago, I stuck out my tongue and mastered drawing lines using the Bresenham algorithm ...): The


    theoretical line is bold, and the difference hits the eye.

    The problem was temporarily solved by introducing a certain factor, which allowed to proportionally increase the distance between points (while maintaining angular distances), which made it possible to smooth out the difference between points and make the calculation more accurate, as a result we get 23 points instead of 61, more than for straight lines, but for my purposes enough for now.

    To summarize:




    The editor is ready, allows you to upload an image, scale, move the mouse, add new objects and edit existing ones, everything works on a strange mixture of SVG and Canvas.

    In the future I plan to describe my torment with CANVAS and the translation of work with objects on SVG, about combining objects on the map and in the list, as well as about why all this was needed.

    UPD:
    Used the Ramer-Douglas-Pecker algorithm to minimize the number of points, the result became much better, the nodal points are determined more precisely. Thanks LevshinO for the idea!

    UPD:
    Uploaded the second part of the story of creation editor, including with reference to the source.

    Also popular now: