web-dev-qa-db-fra.com

Div déplaçable sans interface jQuery

Comme le titre l'indique, j'essaie de rendre une div déplaçable sans utiliser l'interface utilisateur de jQuery.

Cependant, je suis coincé avec le code ci-dessous. Je comprends que je vais utiliser la position de la souris par rapport au conteneur div (dans lequel le div doit être déplacé) et que je définirai le décalage des div par rapport à ces valeurs.

Je n'arrive pas à comprendre comment. Des indices pour moi?

Ce code ne fonctionne pas (bien sûr):

var X, Y;

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

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

Voici un exemple simple vraiment qui pourrait vous aider à démarrer:

$(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;
    });
});

Exemple: http://jsfiddle.net/Jge9z/

Je comprends que je vais utiliser la position de la souris par rapport au conteneur div (dans lequel le div doit être déplacé) et que je définirai le décalage des div par rapport à ces valeurs.

Pas si sûr de ça. Il me semble qu'en glisser-déposer, vous voudriez toujours utiliser le décalage des éléments par rapport au document.

Si vous voulez dire que vous voulez limiter le glissement vers une zone particulière, c'est un problème plus compliqué (mais toujours réalisable).

74
Andrew Whitaker

Voici un autre code mis à jour:

$(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');
    });
});​

Démo: http://jsfiddle.net/tovic/Jge9z/31/


J'ai créé un plugin simple à ce fil.

// 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);

Démo: http://tovic.github.io/dte-project/jquery-draggable/index.html

42
Taufik Nurrohman

Voici ma contribution:

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

voici une autre façon de faire un objet glissable qui est centré au clic

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

Aucune solution JQuery - Basic

Le code glissable le plus élémentaire serait:

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

}

et ensuite usage (non-jquery):

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

ou en jquery:

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

Remarque: l'élément déplacé doit avoir un position:absolute ou position:fixed lui a été appliqué pour le mouvement de gauche, en haut pour fonctionner ...

le code ci-dessous présente quelques fonctionnalités plus "avancées": dragStart, rappels dragStop, ajout de classes css pour supprimer la sélection de texte d'autres éléments lors du glissement, et une fonctionnalité de suppression également ...

commander le code suivant:

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

il définit essentiellement un événement 'mousedown' sur l'élément à déplacer, puis lie et dissocie le document mousem pour supprimer le mouvement.

Poignée glissable

afin de définir un handle glissable pour l'élément

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

}

Le code ci-dessus est utilisé comme suit:

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

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

Ajout de CSS pour éliminer le texte sélectionnable

Le problème maintenant, c’est que lors du glissement, le texte dans l’élément glissable est sélectionné de manière ennuyeuse sans aucune utilisation ...

C'est pourquoi nous avons ajouté les classes draggable et dragging à l'élément. ce qui annulera ce comportement indésirable et ajoutera également un curseur de déplacement pour indiquer que cet élément est déplaçable

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

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

Ajout d'événements

Alors maintenant que nous avons notre élément déplaçable, nous avons parfois besoin d'appeler divers événements.

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

Chacun passera l'événement de souris d'origine au gestionnaire spécifique

Enfin, c'est ce que nous obtenons ...

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

}

Et pour utiliser ceci:

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);

notez que e.target est une référence à notre élément déplaçable

6
levi

Faire glisser comme jQueryUI: JsFiddle

Vous pouvez faire glisser l'élément de n'importe quel point sans un centrage étrange.

$(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

C'est à moi. http://jsfiddle.net/pd1vojsL/

3 boutons pouvant être déplacés dans un div, le glissement étant contraint par 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>

Requiert JQuery (uniquement):

$(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

Ce que j'ai vu ci-dessus est compliqué .....

Voici un code peut se référer.

$("#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});

                }
            })

dragging, dragX, dragY peut être placé en tant que variable globale.

C'est une émission simple sur ce problème, mais il y a un problème avec cette méthode.

Si c'est votre besoin maintenant, voici le Exemple ici.

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.