How to implement a drag-and-drop div from scratch with JavaScript?

前端 未结 8 671
孤独总比滥情好
孤独总比滥情好 2020-12-08 05:07

It should be a combination of CSS and JavaScript. The steps to do should be:

  1. Make it on top of all other elements (which property to specify?)
  2. Catch t
相关标签:
8条回答
  • 2020-12-08 05:14

    You can do this by using following code

    $(function() { 
            $("#imageListId").sortable({ 
                update: function(event, ui) { 
                        getIdsOfImages(); 
                    } //end update          
            }); 
        }); 
      
        function getIdsOfImages() { 
            var values = []; 
            $('.listitemClass').each(function(index) { 
                values.push($(this).attr("id") 
                            .replace("imageNo", "")); 
            }); 
            $('#outputvalues').val(values); 
        }
    /* text align for the body */
        body { 
            text-align: center; 
        } 
          
        /* image dimension */
        img { 
            height: 200px; 
            width: 350px; 
        } 
          
        /* imagelistId styling */
        #imageListId { 
            margin: 0; 
            padding: 0; 
            list-style-type: none; 
        } 
           
        #imageListId div { 
            margin: 0 4px 4px 4px; 
            padding: 0.4em; 
            display: inline-block; 
        } 
          
        /* Output order styling */
        #outputvalues { 
            margin: 0 2px 2px 2px; 
            padding: 0.4em; 
            padding-left: 1.5em; 
            width: 250px; 
            border: 2px solid dark-green; 
            background: gray; 
        } 
           
        .listitemClass { 
            border: 1px solid #006400; 
            width: 350px; 
        } 
           
        .height { 
            height: 10px; 
        }
    <link href="https://code.jquery.com/ui/1.10.4/themes/ui-lightness/jquery-ui.css" rel="stylesheet"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
    
    <!DOCTYPE html> 
    <html> 
    <head> 
        <title> 
            Drag Drop feature
        </title> 
    </head> 
           
    <body> 
        <h1 style="color:green">GeeksforGeeks</h1>  
          
        <b>Drag and drop using jQuery UI Sortable</b> 
          
        <div class="height"></div><br> 
          
        <div id = "imageListId"> 
            <div id="imageNo1" class = "listitemClass"> 
                <img src="images/geeksimage1.png" alt=""> 
            </div> 
              
            <div id="imageNo2" class = "listitemClass"> 
                <img src="images/geeksimage2.png" alt=""> 
            </div> 
              
            <div id="imageNo3" class = "listitemClass"> 
                <img src="images/geeksimage3.png" alt=""> 
            </div> 
              
            <div id="imageNo4" class = "listitemClass"> 
                <img src="images/geeksimage4.png" alt=""> 
            </div> 
              
            <div id="imageNo5" class = "listitemClass"> 
                <img src="images/geeksimage5.png" alt=""> 
            </div> 
              
            <div id="imageNo6" class = "listitemClass"> 
                <img src="images/geeksimage6.png" alt=""> 
            </div> 
        </div> 
          
        <div id="outputDiv"> 
            <b>Output of ID's of images : </b> 
            <input id="outputvalues" type="text" value="" /> 
        </div> 
    </body> 
      
    </html>

    0 讨论(0)
  • 2020-12-08 05:19

    The standard Drag and Drop API is widely recognized to suck big hairy donkey balls. So I wouldn't recommend doing it from scratch. But since that's your question, there are one set of requirements for making something draggable, and one set of requirements for properly setting up a drop zone:

    Dragging:

    • The dom node must have the "draggable" property set to true

    Note: e.dataTransfer.setDragImage can be used to set an alternate drag image (the default is a transparent image of the dom node being dragged.

    Note2: e.dataTransfer.setData can be used inside the dragstart event to set some data that can be gotten back from the drop event.

    Dropping:

    • In the dragover event, e.preventDefault must be called
    • In the drop event, e.preventDefault must be called

    Example:

    <body>
        <div id="dragme" draggable="true">Drag Me</div>
        <div id="dropzone">Drop Here</div>
    </body>
    
    <script>
        var dragme = document.getElementById('dragme')
        var dropzone = document.getElementById('dropzone')
    
        dragme.addEventListener('dragstart',function(e){
            dropzone.innerHTML = "drop here"
        })
    
        dropzone.addEventListener('dragover',function(e){
            e.preventDefault()
        })
        dropzone.addEventListener('drop',function(e){
            e.preventDefault()
            dropzone.innerHTML = "dropped"
        })
    </script>
    

    However, there are a whole lot of gotchas in using this API, including that:

    • it takes a lot of work to distinguish between a dragmove event over a dropzone and a dragmove event related to a draggable item
    • dragmove fires even if your mouse isn't moving
    • dragleave and dragenter fire even if your mouse isn't moving in or out of the listening dom node (it fires whenever it crosses a child-parent bounary for some stupid reason)
    • And more..

    A better way

    I wrote a drag and drop library that makes it a ton easier to use the standard drag and drop API without all those gotchas. Check it out here:

    https://github.com/fresheneesz/drip-drop

    0 讨论(0)
  • 2020-12-08 05:22

    function allowDrop(ev) {
        ev.preventDefault();
    }
    
    function drag(ev) {
        ev.dataTransfer.setData("text", ev.target.id);
    }
    
    function drop(ev) {
        ev.preventDefault();
        var data = ev.dataTransfer.getData("text");
        ev.target.appendChild(document.getElementById(data));
    }
    .mydiv {
        float: left;
        width: 100px;
        height: 35px;
        margin: 10px;
        padding: 10px;
        border: 1px solid black;
    }
    <!DOCTYPE HTML>
    <html>
    <head>
    
    
    </head>
    <body>
    
    <h2>Drag and Drop</h2>
    
    
    <div id="div1" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)">
      <img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" draggable="true" ondragstart="drag(event)" id="drag1" width="88" height="31">
    </div>
    
    <div id="div2" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <div id="div3" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    <div id="div4" class="mydiv" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
    
    </body>
    </html>

    0 讨论(0)
  • 2020-12-08 05:22
    1. To bring the div on top of other elements you have to assign it a high z-index. Additionally, you can set box-shadow to give a feedback to the user that the element is draggable.
    2. You have to listen for a total of three events: mousedown, mouseup, and mousemove. On mousedown you have to attach a listener on mousemove, which tracks the mouse pointer movements and moves the div accordingly, and on mouseup you have to remove the listener on mousemove.
    3. Moving the div with the mouse is a bit tricky. If you translate the div to the pointer's position, the pointer will always point to the top left corner of the div, even when you click at the bottom right corner. For this, you have to calculate the coordinate difference between the div (top left corner) and the mouse pointer, in the mousedown event handler. Then, you have to subtract that difference from the mouse position before translating the div to that position, in the mousemove event handler.

    See the demo for a better idea.

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <meta http-equiv="X-UA-Compatible" content="ie=edge" />
        <title>Document</title>
        <style>
          body,
          html {
            width: 100%;
            height: 100%;
            padding: 0px;
            margin: 0px;
          }
          #box {
            width: 100px;
            height: 100px;
            margin: auto;
            background-color: lightblue;
          }
          #box:active {
            border: 1px solid black;
            box-shadow: 2px 2px 5px 5px #bbb6b6;
          }
        </style>
      </head>
      <body>
        <div id="box"></div>
      </body>
      <script>
        var box = document.getElementById("box");
        var diff = {};
        var getBoxPos = function() {
          return {
            x: box.getBoundingClientRect().x,
            y: box.getBoundingClientRect().y
          };
        };
        var calcDiff = function(x, y) {
          var boxPos = getBoxPos();
          diff = {
            x: x - boxPos.x,
            y: y - boxPos.y
          };
        };
        var handleMouseMove = function(event) {
          var x = event.x;
          var y = event.y;
          x -= diff.x;
          y -= diff.y;
    
          console.log("X " + x + " Y " + y);
          box.style.position = "absolute";
          box.style.transform = "translate(" + x + "px ," + y + "px)";
        };
    
        box.addEventListener("mousedown", function(e) {
          calcDiff(e.x, e.y);
          box.addEventListener("mousemove", handleMouseMove, true);
        });
    
        box.addEventListener("mouseup", function(e) {
          console.log("onmouseup");
          box.removeEventListener("mousemove", handleMouseMove, true);
        });
      </script>
    </html>
    
    0 讨论(0)
  • 2020-12-08 05:23

    Yeah, you can use jQuery if you want a bloated library with far more functions than you need! Or if you want to be more of an elitist, use Waltern Zorn's drag and drop library, which is one tenth of the size.

    0 讨论(0)
  • 2020-12-08 05:24

    The jQuery Way:

    Check out the jQueryUI addons draggable and droppable.

    Literally hundreds of hours have been invested into the jQuery framework to make complicated tasks like this almost trivial. Take advantage of the jQuery team's efforts to make programming rich cross-browser applications easier on us all ;)

    Chuck Norris' Way:

    If you insist on trying this with raw javascript. You'll want to do a few things. One, programmatically set all draggable items to a relative/absolute positioning. If you click a particular item, cause it's top/left values in CSS to reflect the changes made by the x,y axis of the mouse until the click is released. Additionally, you'll want to update the z-index of each draggable when it's clicked to bring it into view.

    Tutorial: How to Drag and Drop with Javascript

    0 讨论(0)
提交回复
热议问题