jQuery drag and draw
Asked Answered
G

2

21

I'm trying to build a jQuery plugin that allows you to drag and draw a rectangle (or a div with a border) but I'm not sure how to do it. I don't know of any that currently have this ability so I don't know where to look for an example of how to do this.

How can I implement drag and draw in jQuery?

Gatha answered 16/1, 2012 at 18:47 Comment(0)
D
51

The basics for something like this are quite simple, when you think about it:

  • Listen for mousedown events on some container (possible the entire document);
    • Place an absolutely positioned element at the position of the mouse, using the mouse coordinates from the event object (e.pageX and e.pageY);
    • Start listening to mousemove events to change the width and height object (based on the mouse coordinates);
  • Listen for the mouseup event to detach the mousemove event listener.

The aforementioned absolute placed element is, e.g., a <div> with a border and background: transparent.

Update: here is an example:

$(function() {
    var $container = $('#container');
    var $selection = $('<div>').addClass('selection-box');

    $container.on('mousedown', function(e) {
        var click_y = e.pageY;
        var click_x = e.pageX;

        $selection.css({
          'top':    click_y,
          'left':   click_x,
          'width':  0,
          'height': 0
        });
        $selection.appendTo($container);

        $container.on('mousemove', function(e) {
            var move_x = e.pageX,
                move_y = e.pageY,
                width  = Math.abs(move_x - click_x),
                height = Math.abs(move_y - click_y),
                new_x, new_y;

            new_x = (move_x < click_x) ? (click_x - width) : click_x;
            new_y = (move_y < click_y) ? (click_y - height) : click_y;

            $selection.css({
              'width': width,
              'height': height,
              'top': new_y,
              'left': new_x
            });
        }).on('mouseup', function(e) {
            $container.off('mousemove');
            $selection.remove();
        });
    });
});

Demo: http://jsbin.com/ireqix/226/

Dior answered 16/1, 2012 at 19:2 Comment(8)
For the sake of anyone following along, I updated your answer with the solution to the dragging in different directions.Gatha
And I needed something just like this for a quick html image mapper (rectangles only suited my needs). Incorporates the drag-both-ways change as above, and outputs html image-map source. jsbin.com/ireqix/91Arium
When you moving the selection box around quickly (but still within the document area) the origin position seems to get messed up sometimes, but when you continue moving it seems to pop back to the correct location. For example, if you move back and forth right/left, eventually the origin location gets offset. Any idea why this happens?Garnettgarnette
I think the problem is that the x position (but the same applies to the y coordinate as well) is adjusted left when the mouse moves left of the origin, but is never adjusted back to the right when the mouse moves right again. Putting an else clause that sets the x position back to the original click_x seems to resolve this.Garnettgarnette
@Garnettgarnette You're absolutely right. I rewrote the code slightly to circumvent the issue. Thanks for the heads-up!Dior
This kind of thing (community collaboration) is why I still love SOFairhaired
jsbin demos not working anymore - getting ReferenceError: Can't find variable: $ errors in the console. Running locally on my dev machine and local browser works. Note also that mouseup events are not removed and pile up so a call to $container.off('mouseup'); is also needed. improved jsbin hereLuck
ummm... jsbin is a buggy nightmare - here is the working code on jsfiddle jsfiddle.net/tcab/hay4op0t note I have extracted the box calculation function so that the box can be reported on the mouseup. Also I untangled the chained handlers into separate functions which I think is clearer to understand.Luck
A
0
$("#YOUR_ELEMENT_ID").on("mousedown", function (e) {
    var click_x = e.pageX;
    var click_y = e.pageY;

    /* Posição do objeto */
    var x = parseFloat($(this).css("left").replace("px", "")),
        y = parseFloat($(this).css("top").replace("px", ""));
    /* Calcula distância no eixo x */
    var distanc_x = Math.abs(x - click_x);
    var distanc_y = Math.abs(y - click_y);

    $("#YOUR_ELEMENT_ID")
        .on("mousemove", function (e) {

            var new_x = e.pageX - distanc_x;
            var new_y = e.pageY - distanc_y;

            $(this).css({
                top: new_y,
                left: new_x,
            });

        }).on("mouseup", function (e) {
        $(this).off("mousemove");
    });

});
Amsterdam answered 6/4, 2019 at 3:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.