it-swarm-pt.tech

Div dragável sem jQuery UI

Como o título diz, eu estou tentando fazer um div draggable sem usar jQuery UI.

No entanto, eu estou preso com o código abaixo. Eu entendo que vou usar a posição do mouse em relação ao contêiner div (no qual o div deve ser arrastado) e que devo definir o deslocamento divs relativo a esses valores.

Eu simplesmente não consigo descobrir como. Alguma pista para mim?

Este código não funciona (é claro):

var X, Y;

$(this).mousedown(function() {
    $(this).offset({ 
        left: X, 
        top: Y
    });
});

$("#containerDiv").mousemove(function(event) {
    X = event.pageX;
    Y = event.pageY;
});
58
holyredbeard

Aqui está um exemplo simples really que pode ajudá-lo a começar:

$(document).ready(function() {
    var $dragging = null;

    $(document.body).on("mousemove", function(e) {
        if ($dragging) {
            $dragging.offset({
                top: e.pageY,
                left: e.pageX
            });
        }
    });


    $(document.body).on("mousedown", "div", function (e) {
        $dragging = $(e.target);
    });

    $(document.body).on("mouseup", function (e) {
        $dragging = null;
    });
});

Exemplo: http://jsfiddle.net/Jge9z/

Eu entendo que vou usar a posição do mouse em relação ao contêiner div (no qual o div deve ser arrastado) e que devo definir o deslocamento divs relativo a esses valores.

Não tenho tanta certeza disso. Parece-me que em arrastar e soltar você sempre deseja usar o deslocamento dos elementos relativos ao documento.

Se você quiser restringir o arrastamento a uma área específica, isso é um problema mais complicado (mas ainda factível).

74
Andrew Whitaker

Aqui está outro código atualizado:

$(document).ready(function() {
    var $dragging = null;
    $('body').on("mousedown", "div", function(e) {
        $(this).attr('unselectable', 'on').addClass('draggable');
        var el_w = $('.draggable').outerWidth(),
            el_h = $('.draggable').outerHeight();
        $('body').on("mousemove", function(e) {
            if ($dragging) {
                $dragging.offset({
                    top: e.pageY - el_h / 2,
                    left: e.pageX - el_w / 2
                });
            }
        });
        $dragging = $(e.target);
    }).on("mouseup", ".draggable", function(e) {
        $dragging = null;
        $(this).removeAttr('unselectable').removeClass('draggable');
    });
});​

Demo: http://jsfiddle.net/tovic/Jge9z/31/


Eu criei um plugin simples para este segmento.

// Simple JQuery Draggable Plugin
// https://plus.google.com/108949996304093815163/about
// Usage: $(selector).drags();
// Options:
// handle            => your dragging handle.
//                      If not defined, then the whole body of the
//                      selected element will be draggable
// cursor            => define your draggable element cursor type
// draggableClass    => define the draggable class
// activeHandleClass => define the active handle class
//
// Update: 26 February 2013
// 1. Move the `z-index` manipulation from the plugin to CSS declaration
// 2. Fix the laggy effect, because at the first time I made this plugin,
//    I just use the `draggable` class that's added to the element
//    when the element is clicked to select the current draggable element. (Sorry about my bad English!)
// 3. Move the `draggable` and `active-handle` class as a part of the plugin option
// Next update?? NEVER!!! Should create a similar plugin that is not called `simple`!

(function($) {
    $.fn.drags = function(opt) {

        opt = $.extend({
            handle: "",
            cursor: "move",
            draggableClass: "draggable",
            activeHandleClass: "active-handle"
        }, opt);

        var $selected = null;
        var $elements = (opt.handle === "") ? this : this.find(opt.handle);

        $elements.css('cursor', opt.cursor).on("mousedown", function(e) {
            if(opt.handle === "") {
                $selected = $(this);
                $selected.addClass(opt.draggableClass);
            } else {
                $selected = $(this).parent();
                $selected.addClass(opt.draggableClass).find(opt.handle).addClass(opt.activeHandleClass);
            }
            var drg_h = $selected.outerHeight(),
                drg_w = $selected.outerWidth(),
                pos_y = $selected.offset().top + drg_h - e.pageY,
                pos_x = $selected.offset().left + drg_w - e.pageX;
            $(document).on("mousemove", function(e) {
                $selected.offset({
                    top: e.pageY + pos_y - drg_h,
                    left: e.pageX + pos_x - drg_w
                });
            }).on("mouseup", function() {
                $(this).off("mousemove"); // Unbind events from document
                if ($selected !== null) {
                    $selected.removeClass(opt.draggableClass);
                    $selected = null;
                }
            });
            e.preventDefault(); // disable selection
        }).on("mouseup", function() {
            if(opt.handle === "") {
                $selected.removeClass(opt.draggableClass);
            } else {
                $selected.removeClass(opt.draggableClass)
                    .find(opt.handle).removeClass(opt.activeHandleClass);
            }
            $selected = null;
        });

        return this;

    };
})(jQuery);

Demonstração: http://tovic.github.io/dte-project/jquery-draggable/index.html

42
Taufik Nurrohman

Aqui está minha contribuição:

http://jsfiddle.net/g6m5t8co/1/

<!doctype html>
<html>
    <head>
        <style>
            #container {
                position:absolute;
                background-color: blue;
                }
            #elem{
                position: absolute;
                background-color: green;
                -webkit-user-select: none;
                -moz-user-select: none;
                -o-user-select: none;
                -ms-user-select: none;
                -khtml-user-select: none;     
                user-select: none;
            }
        </style>
        <script>
            var mydragg = function(){
                return {
                    move : function(divid,xpos,ypos){
                        divid.style.left = xpos + 'px';
                        divid.style.top = ypos + 'px';
                    },
                    startMoving : function(divid,container,evt){
                        evt = evt || window.event;
                        var posX = evt.clientX,
                            posY = evt.clientY,
                        divTop = divid.style.top,
                        divLeft = divid.style.left,
                        eWi = parseInt(divid.style.width),
                        eHe = parseInt(divid.style.height),
                        cWi = parseInt(document.getElementById(container).style.width),
                        cHe = parseInt(document.getElementById(container).style.height);
                        document.getElementById(container).style.cursor='move';
                        divTop = divTop.replace('px','');
                        divLeft = divLeft.replace('px','');
                        var diffX = posX - divLeft,
                            diffY = posY - divTop;
                        document.onmousemove = function(evt){
                            evt = evt || window.event;
                            var posX = evt.clientX,
                                posY = evt.clientY,
                                aX = posX - diffX,
                                aY = posY - diffY;
                                if (aX < 0) aX = 0;
                                if (aY < 0) aY = 0;
                                if (aX + eWi > cWi) aX = cWi - eWi;
                                if (aY + eHe > cHe) aY = cHe -eHe;
                            mydragg.move(divid,aX,aY);
                        }
                    },
                    stopMoving : function(container){
                        var a = document.createElement('script');
                        document.getElementById(container).style.cursor='default';
                        document.onmousemove = function(){}
                    },
                }
            }();

        </script>
    </head>
    <body>
        <div id='container' style="width: 600px;height: 400px;top:50px;left:50px;">     
            <div id="elem" onmousedown='mydragg.startMoving(this,"container",event);' onmouseup='mydragg.stopMoving("container");' style="width: 200px;height: 100px;">
                <div style='width:100%;height:100%;padding:10px'>
                <select id=test>
                    <option value=1>first
                    <option value=2>second
                </select>
                <INPUT TYPE=text value="123">
                </div>
            </div>
        </div>  
    </body>
</html>
13
niente00

aqui está outra maneira de criar um objeto arrastável centralizado no clique

http://jsfiddle.net/pixelass/fDcZS/

function endMove() {
    $(this).removeClass('movable');
}

function startMove() {
    $('.movable').on('mousemove', function(event) {
        var thisX = event.pageX - $(this).width() / 2,
            thisY = event.pageY - $(this).height() / 2;

        $('.movable').offset({
            left: thisX,
            top: thisY
        });
    });
}
$(document).ready(function() {
    $("#containerDiv").on('mousedown', function() {
        $(this).addClass('movable');
        startMove();
    }).on('mouseup', function() {
        $(this).removeClass('movable');
        endMove();
    });

});

CSS

#containerDiv {
    background:#333;
    position:absolute;
    width:200px;
    height:100px;
}
8
user950658

Arrastando como jQueryUI: JsFiddle

Você pode arrastar o elemento de qualquer ponto sem uma centralização estranha.

$(document).ready(function() {

        var $body = $('body');
        var $target = null;
        var isDraggEnabled = false;

        $body.on("mousedown", "div", function(e) {

            $this = $(this);
            isDraggEnabled = $this.data("draggable");

            if (isDraggEnabled) {
                if(e.offsetX==undefined){
                    x = e.pageX-$(this).offset().left;
                    y = e.pageY-$(this).offset().top;
                }else{
                    x = e.offsetX;
                    y = e.offsetY;
                };

                $this.addClass('draggable');
                $body.addClass('noselect');
                $target = $(e.target);
            };

        });

         $body.on("mouseup", function(e) {
            $target = null;
            $body.find(".draggable").removeClass('draggable');
            $body.removeClass('noselect');
        });

         $body.on("mousemove", function(e) {
            if ($target) {
                $target.offset({
                    top: e.pageY  - y,
                    left: e.pageX - x
                });
            };     
         });

    });
6
Sams

Solução No Jquery - Básica

O código arrastável mais básico seria:

Element.prototype.drag = function(){

   var mousemove = function(e){ // document mousemove

       this.style.left = ( e.clientX - this.dragStartX ) + 'px';
       this.style.top  = ( e.clientY - this.dragStartY ) + 'px';

   }.bind(this);

   var mouseup = function(e){ // document mouseup

       document.removeEventListener('mousemove',mousemove);
       document.removeEventListener('mouseup',mouseup);

   }.bind(this);

   this.addEventListener('mousedown',function(e){ // element mousedown

       this.dragStartX = e.offsetX;
       this.dragStartY = e.offsetY;

       document.addEventListener('mousemove',mousemove);
       document.addEventListener('mouseup',mouseup);

   }.bind(this));

   this.style.position = 'absolute' // fixed might work as well

}

e, em seguida, uso (não-jquery):

document.querySelector('.target').drag();

ou no jquery:

$('.target')[0].drag();

Aviso: o elemento arrastado deve ter um position:absolute ou position:fixed aplicado a ele para o movimento superior esquerdo para trabalhar ...

o codepen abaixo tem alguns recursos mais "avançados": dragStart, callbacks dragStop, classes css anexando para remover a seleção de texto de outros elementos enquanto arrasta, e um recurso drop também ...

checkout o seguinte codepen:

http://codepen.io/anon/pen/VPPaEK

é basicamente definir um evento 'mousedown' no elemento que precisa ser arrastado e, em seguida, vincular e desvincular o mousemove do documento para lidar com o movimento.

Alça arrastável

a fim de definir um identificador arrastável para o elemento

Element.prototype.drag = function( setup ){

   var setup = setup || {};

   var mousemove = function(e){ // document mousemove

       this.style.left = ( e.clientX - this.dragStartX ) + 'px';
       this.style.top  = ( e.clientY - this.dragStartY ) + 'px';

   }.bind(this);

   var mouseup = function(e){ // document mouseup

       document.removeEventListener('mousemove',mousemove);
       document.removeEventListener('mouseup',mouseup);

   }.bind(this);

   var handle = setup.handle || this;

   handle.addEventListener('mousedown',function(e){ // element mousedown

       this.dragStartX = e.offsetX;
       this.dragStartY = e.offsetY;

       document.addEventListener('mousemove',mousemove);
       document.addEventListener('mouseup',mouseup);

       handle.classList.add('dragging');

   }.bind(this)); 

   handle.classList.add('draggable');

   this.style.position = 'absolute' // fixed might work as well

}

O código acima é usado da seguinte maneira:

var setup = {
   handle : document.querySelector('.handle')
};

document.querySelector('.box').drag(setup);

Adicionando CSS para eliminar o texto selecionável

O problema agora é que, ao arrastar, o texto dentro do elemento arrastável é selecionado irritantemente sem uso ...

É por isso que adicionamos as classes draggable e dragging ao elemento. que cancelará esse comportamento indesejado e também adicionará um cursor de movimento para mostrar que esse elemento pode ser arrastado

.draggable{
    cursor: move;
    position: fixed;
}

.draggable.dragging{
    user-select: none;
}

Adicionando eventos

Então, agora que temos o nosso elemento draggable, às vezes precisamos chamar vários eventos.

setup.ondraginit  // this is called when setting up the draggable
setup.ondragstart // this is called when mouse is down on the element
setup.ondragend   // this is called when mouse is released (after dragging)
setup.ondrag      // this is called while the element is being dragged

Cada um passará o evento do mouse original para o manipulador específico

Finalmente, é isso que obtemos ...

Element.prototype.drag = function( setup ){

    var setup = setup || {};

    var mousemove = function(e){ // document mousemove

        this.style.left = ( e.clientX - this.dragStartX ) + 'px';
        this.style.top  = ( e.clientY - this.dragStartY ) + 'px';

        setup.ondrag && setup.ondrag(e); // ondrag event

    }.bind(this);

    var mouseup = function(e){ // document mouseup

        document.removeEventListener('mousemove',mousemove);
        document.removeEventListener('mouseup',mouseup);

        handle.classList.remove('dragging');

        setup.ondragend && setup.ondragend(e); // ondragend event

    }.bind(this);

    var handle = setup.handle || this;

    handle.addEventListener('mousedown',function(e){ // element mousedown

        this.dragStartX = e.offsetX;
        this.dragStartY = e.offsetY;

        document.addEventListener('mousemove',mousemove);
        document.addEventListener('mouseup',mouseup);

        handle.classList.add('dragging');

        setup.ondragstart && setup.ondragstart(e); // ondragstart event

    }.bind(this)); 

    handle.classList.add('draggable');

    setup.ondraginit && setup.ondraginit(e); // ondraginit event

}

E para usar isso:

var setup = {
   handle      : document.querySelector('.handle'),
   ondragstart : e => { console.log('drag has started!'); },
   ondrag      : e => { console.log('drag!'); },
   ondragend   : e => { console.log('drag has ended!'); }
};

document.querySelector('.box').drag(setup);

note que e.target é uma referência ao nosso elemento draggable

5
levi

Isso é meu. http://jsfiddle.net/pd1vojsL/

3 botões arrastáveis ​​em uma div, arrastando restringidos por div.

<div id="parent" class="parent">
    <button id="button1" class="button">Drag me</button>
    <button id="button2" class="button">Drag me</button>
    <button id="button3" class="button">Drag me</button>
</div>
<div id="log1"></div>
<div id="log2"></div>

Requer JQuery (apenas):

$(function() {
    $('.button').mousedown(function(e) {
        if(e.which===1) {
            var button = $(this);
            var parent_height = button.parent().innerHeight();
            var top = parseInt(button.css('top')); //current top position
            var original_ypos = button.css('top','').position().top; //original ypos (without top)
            button.css({top:top+'px'}); //restore top pos
            var drag_min_ypos = 0-original_ypos;
            var drag_max_ypos = parent_height-original_ypos-button.outerHeight();
            var drag_start_ypos = e.clientY;
            $('#log1').text('mousedown top: '+top+', original_ypos: '+original_ypos);
            $(window).on('mousemove',function(e) {
                //Drag started
                button.addClass('drag');
                var new_top = top+(e.clientY-drag_start_ypos);
                button.css({top:new_top+'px'});
                if(new_top<drag_min_ypos) { button.css({top:drag_min_ypos+'px'}); }
                if(new_top>drag_max_ypos) { button.css({top:drag_max_ypos+'px'}); }
                $('#log2').text('mousemove min: '+drag_min_ypos+', max: '+drag_max_ypos+', new_top: '+new_top);
                //Outdated code below (reason: drag contrained too early)
                /*if(new_top>=drag_min_ypos&&new_top<=drag_max_ypos) {
                    button.css({top:new_top+'px'});
                }*/
            });
            $(window).on('mouseup',function(e) {
                 if(e.which===1) {
                    //Drag finished
                    $('.button').removeClass('drag');
                    $(window).off('mouseup mousemove');
                    $('#log1').text('mouseup');
                    $('#log2').text('');
                 }
            });
        }
    });
});
4
Richard

O que vi acima é complicado .....

Aqui está um código que você pode se referir.

$("#box").on({
                mousedown:function(e)
                {
                  dragging = true;
                  dragX = e.clientX - $(this).position().left;
                  //To calculate the distance between the cursor pointer and box 
                  dragY = e.clientY - $(this).position().top;
                },
                mouseup:function(){dragging = false;},
                  //If not set this on/off,the move will continue forever
                mousemove:function(e)
                {
                  if(dragging)
                  $(this).offset({top:e.clientY-dragY,left:e.clientX-dragX});

                }
            })

arrastar, dragX, dragY podem ser a variável global.

É um programa simples sobre esse problema, mas há algum bug sobre esse método.

Se for sua necessidade agora, aqui está o exemplo aqui.

2
Hsinhsin Hung
$(document).ready(function() {
    var $startAt = null;

    $(document.body).live("mousemove", function(e) {
        if ($startAt) {
            $("#someDiv").offset({
                top: e.pageY,
                left: $("#someDiv").position().left-$startAt+e.pageX
            });
            $startAt = e.pageX; 
        }
    });

    $("#someDiv").live("mousedown", function (e) {$startAt = e.pageX;});
    $(document.body).live("mouseup", function (e) {$startAt = null;});
});
0
Wasim A.