Client-side sprinkler on canvas

    At one of the projects, it was necessary to make a crop for avatars loaded by users. Standard solutions, such as Jcrop, after selecting the area, send the coordinates to the server, and the image crop itself must be implemented already on the server. Meanwhile, modern browsers have already reached the point where such actions can be carried out immediately on the client. This prompted me to write my own crop using canvas, which would perform all the actions on the client and send the finished image in the form of a base64 string to the server. In addition to speeding up the work and unloading the server, it will also allow us to immediately change the user avatar on the page, without loading it from the server.



    Technology and challenge


    Kropalka was written in CoffeeScript - a small language compiled in JavaScript. Decorated Kropalka as a plugin for jQuery. After loading the image, we set the crop on it - it will draw a canvas over the image with the possibility of highlighting the area. After each change of the selected area, a new picture is recorded in the image data and can be easily accessed from the outside. Kropalka should allow you to include previews, establish a fixed aspect ratio and set the selection immediately after activation. And, of course, cropping should work in all major browsers.

    Implementation


    The selection area and the corners beyond which the area can be stretched are represented by the class Rect. There is nothing magical in it - properties with coordinates, methods for determining the hit of a point and updating coordinates. The class EvroneCropis responsible for creating the canvas, drawing it on top of the picture, hanging handlers and saving the cropped picture in data.

    To save the resulting image a temporary element of the canvas, the coordinates are calculated based on the original image size, using the method of drawImage()the selected area is drawn into a temporary the canvas, and using the method toDataURL()of canvasa resultant image that is in the form of base64 strings can be passed to the server and save.

    In our case, the following code is used for saving on the server (Ruby):
    encoded_image = params[:image].sub('data:image/png;base64,', '')
    avatar_io = FilelessIO.new(Base64.decode64(encoded_image))
    avatar_io.original_filename = "avatar.png" # любое значение, обязательный параметр для CarrierWave
    Rails.logger.info "IO: #{avatar_io.inspect}"
    @user.avatar = avatar_io
    @user.save
    


    When creating a sprinkler, you can pass the following parameters:
    $(this).evroneCrop({
        preview: '#preview1',     //селектор элемента img, в котором отображать превью
        size: {w: 150, h: 150},   //размер результирующего изображения
        ratio: 1,                 //отношение сторон области выделения, в данном случае - квадрат
        setSelect: 'center',      //установка выделения по умолчанию
        log: true                 //вывод отладочной информации
    });
    

    All parameters are optional. Demo .

    setSelectcan take a value centerby automatically calculating the center of the image and the size of the selection, or it can take an object {x:0, y: 0, w: 100, h: 100}and set the selection to a given position. If you have the option set, you don’t need ratioto setSelecttransmit the height in the object .

    ratiotakes a number greater than zero, and fixes the sides with a ratio of lengths equal to this number. For example, you can pass 1 for the square or 16/9 for the aspect ratio of 16 to 9.

    Browser Troubles

    The resulting tool works in all major browsers - Chrome, Firefox> 4, Safari, Opera> 11, IE 9. There are plans to write a fallback in flash for IE8. It was originally planned to use Google's excanvas , but it turned out that it does not provide such a method necessary for our task as toDataURL();there is a way out with a flash implementation , but hands have not reached it yet.

    Kropalka is still damp, for example, the installation of the minimum and maximum sizes has not yet been implemented, but it lies on the github , works, and is slowly developing.

    Also popular now: