简体   繁体   中英

How do I only allow an item to be dropped in a certain place in HTML/JavaScript?

Helllo, fellow StackOverflow community! For the past few weeks, I have been working on a drag-and-drop for HTML/JavaScript. Basically, I have a circle and two boxes. The circle can be dragged to anywhere on the screen. However, I need it so the circle can only be dropped within one of the two boxes. Despite several days of research, I could not figure out how to do this. Thank you in advance!

<!DOCTYPE html>
<html>

<head>
  <meta name="viewport" 
        content="width=device-width, 
        initial-scale=1.0, 
        user-scalable=no" />
  <title>Drag/Drop/Bounce</title>
  <style>
    #item {
      width: 100px;
      height: 100px;
      background-color: rgb(245, 230, 99);
      border: 10px solid rgba(136, 136, 136, .5);
      border-radius: 50%;
      touch-action: none;
      user-select: none;
    }

    #box1 {
      width: 200px;
      height: 200px;
      background-color: red;
    }

    #box2 {
      width: 200px;
      height: 200px;
      background-color: lightblue;
    }
  </style>
</head>

<body>
<h1>Drag and Drop</h1>
<div id="box1">
  <div id="item"></div>
</div>
<br>
<div id="box2"></div>

  <script>
    var dragItem = document.querySelector("#item");
    var container = dragItem;

    //Declare Variables
    var active = false;
    var currentX;
    var currentY;
    var initialX;
    var initialY;
    var xOffset = 0;
    var yOffset = 0;

    //Add Event Listeners for Touchscreens
    container.addEventListener("touchstart", dragStart, false);
    container.addEventListener("touchend", dragEnd, false);
    container.addEventListener("touchmove", drag, false);

    //Add Event Listeners for Mice
    container.addEventListener("mousedown", dragStart, false);
    container.addEventListener("mouseup", dragEnd, false);
    container.addEventListener("mousemove", drag, false);

    function dragStart(e) { //when the drag starts
      if (e.type === "touchstart") { //if its a touchscreen
        initialX = e.touches[0].clientX - xOffset; //set initial x-cordinate to where it was before drag started
        initialY = e.touches[0].clientY - yOffset; //set initial y-cordinate to where it was before drag started
      } else { //if its not a touchscreen (mouse)
        initialX = e.clientX - xOffset; //set initial x-cordinate to where it was before drag started
        initialY = e.clientY - yOffset; //set initial y-cordinate to where it was before drag started
      }

      if (e.target === dragItem) { //if user is dragging circle
        active = true; //the drag is active
      }
    }

    function dragEnd(e) { //when the drag ends
      initialX = currentX; //set the initial x-cordinate to where it is now
      initialY = currentY; //set the initial y-cordinate to where it is now

      active = false; //the drag is no longer active
    }

    function drag(e) { //when the circle is being dragged
      if (active) { //if the drag is active
        e.preventDefault(); //the user cant do anything else but drag

        if (e.type === "touchmove") { //if its a touchscreen
          currentX = e.touches[0].clientX - initialX; //set current x-cordinate to where it is now
          currentY = e.touches[0].clientY - initialY; //set current y-cordinate to where it is now
        } else { //if its not a touchscreen (mouse)
          currentX = e.clientX - initialX; //set current x-cordinate to where it is now
          currentY = e.clientY - initialY; //set current y-cordinate to where it is now
        }

        //Im not sure what this does but it dosnt work without it
        xOffset = currentX;
        yOffset = currentY;
        setTranslate(currentX, currentY, dragItem);
      }
    }

    function setTranslate(xPos, yPos, el) { //Im not sure what this does but it dosnt work without it
      el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)";
    }
  </script>
</body>

</html>

I've also uploaded the code to TryIt for those who prefer: https://www.w3schools.com/code/tryit.asp?filename=GCF4V2RIT7T4

In this version you can move the circle only inside the red box. I think you can take that and easily implement the other box.

 <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" /> <title>Drag/Drop/Bounce</title> <style> #item { width: 100px; height: 100px; background-color: rgb(245, 230, 99); border: 10px solid rgba(136, 136, 136, .5); border-radius: 50%; touch-action: none; user-select: none; position: absolute; } #box1 { width: 200px; height: 200px; background-color: red; } #box2 { width: 200px; height: 200px; background-color: lightblue; } </style> </head> <body> <h1>Drag and Drop</h1> <div id="item"></div> <div id="box1"> </div> <br> <div id="box2"></div> <script> var dragItem = document.querySelector("#item"); var box1 = document.querySelector("#box1"); var box2 = document.querySelector("#box2"); var container = dragItem; //Declare Variables var active = false; var currentX; var currentY; var initialX; var initialY; var xOffset = 0; var yOffset = 0; //Add Event Listeners for Touchscreens container.addEventListener("touchstart", dragStart, false); container.addEventListener("touchend", dragEnd, false); container.addEventListener("touchmove", drag, false); //Add Event Listeners for Mice container.addEventListener("mousedown", dragStart, false); container.addEventListener("mouseup", dragEnd, false); container.addEventListener("mousemove", drag, false); function dragStart(e) { //when the drag starts if (e.type === "touchstart") { //if its a touchscreen initialX = e.touches[0].clientX - xOffset; //set initial x-cordinate to where it was before drag started initialY = e.touches[0].clientY - yOffset; //set initial y-cordinate to where it was before drag started } else { //if its not a touchscreen (mouse) initialX = e.clientX - xOffset; //set initial x-cordinate to where it was before drag started initialY = e.clientY - yOffset; //set initial y-cordinate to where it was before drag started } if (e.target === dragItem) { //if user is dragging circle active = true; //the drag is active } } function dragEnd(e) { //when the drag ends const box1Size = box1.getBoundingClientRect() const elementSize = dragItem.getBoundingClientRect() if (elementSize.left >= box1Size.left && elementSize.right <= box1Size.right && elementSize.top >= box1Size.top && elementSize.bottom <= box1Size.bottom) { initialX = currentX; //set the initial x-cordinate to where it is now initialY = currentY; //set the initial y-cordinate to where it is now } else { currentX = 0 currentY = 0 initialX = 0 initialY = 0 xOffset = 0; yOffset = 0; setTranslate(0, 0, dragItem); } active = false; //the drag is no longer active } function drag(e) { //when the circle is being dragged if (active) { //if the drag is active e.preventDefault(); //the user cant do anything else but drag if (e.type === "touchmove") { //if its a touchscreen currentX = e.touches[0].clientX - initialX; //set current x-cordinate to where it is now currentY = e.touches[0].clientY - initialY; //set current y-cordinate to where it is now } else { //if its not a touchscreen (mouse) currentX = e.clientX - initialX; //set current x-cordinate to where it is now currentY = e.clientY - initialY; //set current y-cordinate to where it is now } //Im not sure what this does but it dosnt work without it xOffset = currentX; yOffset = currentY; setTranslate(currentX, currentY, dragItem); } } function setTranslate(xPos, yPos, el) { //Im not sure what this does but it dosnt work without it el.style.transform = "translate3d(" + xPos + "px, " + yPos + "px, 0)"; } </script> </body> </html>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM