59 votes

div draggable sans jQuery UI

J'essaie de faire un div glissant sans utiliser jQuery UI.

Cependant, je suis coincé avec le code ci-dessous. Je comprends que je dois utiliser la position de la souris par rapport au conteneur. div (dans lequel le div sera traînée) et que je dois définir le paramètre div Le décalage de l'utilisateur par rapport à ces valeurs.

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

C'est le code qui 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;
});

75voto

Andrew Whitaker Points 58588

Voici un realmente exemple simple 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 dois utiliser la position de la souris par rapport à la division conteneur (dans laquelle la division doit être glissée) et que je dois définir le décalage des divisions par rapport à ces valeurs.

Je n'en suis pas si sûr. Il me semble qu'avec la fonction glisser-déposer, vous devez toujours vous voulez utiliser le décalage des éléments par rapport au document.

Si vous voulez dire que vous voulez limiter le déplacement à une zone particulière, c'est un problème plus compliqué (mais toujours faisable).

0 votes

Fonctionne très bien, mais le déplacement ne fonctionne pas sur les appareils mobiles. Comment peut-on modifier ce code pour qu'il fonctionne également sur les appareils mobiles ?

0 votes

Je ne suis pas sûr. Vous devriez probablement regarder dans événements tactiles

2 votes

Je suggère d'étendre le code en ajoutant mouseleave événement, comme $("body").mouseleave(function(e) { $dragging = null; }) pour attraper le relâchement d'un bouton pressé en dehors de la fenêtre du navigateur.

43voto

Taufik Nurrohman Points 572

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émonstration : http://jsfiddle.net/tovic/Jge9z/31/


J'ai créé un plugin simple pour ce fil de discussion.

// 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émonstration : http://tovic.github.io/dte-project/jquery-draggable/index.html

2 votes

Si vous utilisez ce code $selected = $(this).parent(); ligne 38:59 vous forcez le développeur à utiliser une structure html fixe. vous supposez que le parent va être l'intégralité de la structure html. structure pour se déplacer, mais si au lieu de cela vous attribuez une classe comme disons class='draggableContainer' vous pouvez faire quelque chose comme $selected = $(this).closest(".draggableContainer"); vous pouvez maintenant utiliser n'importe quelle structure html et cela va fonctionner. Mais en général, c'est cool $hit fonctionne vraiment bien

0 votes

Aussi, si vous utilisez ce simple plugin vous devez réaliser que si vous avez handler events à l'intérieur du conteneur dragable les activera. Vous devez donc vous assurer que tout ce que vous exécutez dans la fonction de ce gestionnaire provient de l'événement attendu et non de l'événement mouseup (drag). Ou essayez d'utiliser event.stopPropagation() dans le plugin, j'ai essayé mais je n'ai pas pu l'arrêter. Je ne savais pas exactement où le mettre.

1 votes

J'utilise ce plugin mais il a un bug majeur lorsque l'élément que vous définissez comme draggable a un élément <select>. La sélection ne fonctionne plus (du moins sur Chrome). Je n'aime pas non plus le problème d'UX qui fait que lorsque l'utilisateur "démarre le drag" au dessus d'un élément d'entrée ou de bouton, le drag s'exécute et ensuite le clic de souris est exécuté. Je préfère ignorer certains éléments pour ne pas déclencher l'événement de glisser. J'ai donc bifurqué sur ce plugin pour avoir une option d'annulation, similaire à jquery-ui : github.com/pjfsilva/dte-project/blob/master/jquery-draggable/ Maintenant <select> fonctionne et l'UX est amélioré

16voto

niente00 Points 21

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>

4 votes

Bon travail... Seulement avec javascript joli +1

2 votes

C'est excellent, le seul problème est que si vous avez un élément positionné de manière absolue, lors du mousedown, il pense qu'il est en haut et à gauche 0 - y a-t-il un moyen simple pour qu'il maintienne sa position actuelle avant de glisser ?

0 votes

@DarrenSweeney : Appelez getBoundingClientRect() para #elem et utiliser ensuite la fonction top / left à init divTop / divLeft ! Bonus : vous n'aurez plus besoin de préréglages, ni de style quoi qu'il en soit, alors.

8voto

pixelass Points 1398

Voici une autre façon de créer un objet glissant qui est centré sur le 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;
}

6voto

Sams Points 116

Déplacement comme jQueryUI : JsFiddle

Vous pouvez faire glisser l'élément à partir de n'importe quel point sans qu'il y ait un centrage bizarre.

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

    });

0 votes

Résultat intéressant. Si vous ajoutez ceci à un div, vous pouvez faire glisser tous ses éléments enfants hors de celui-ci, mais si vous cliquez et faites glisser sur le div lui-même et non sur un enfant, ceci déplace tout.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X