JavaScript如何通过点击拖动动态移动Div

问题描述 投票:0回答:10

好吧,看起来应该很简单。我需要获取一个已经存在的 div 并根据窗口内的鼠标位置移动它。我到处搜索,这导致我以过于复杂的方式做同样的事情,并且涉及到 j-query 的使用。我需要严格使用 javascript 来完成我想做的事情。

方法:

var mousePosition;
var div;

(function createDiv(){

    div = document.createElement("div");
    div.style.position = "absolute";
    div.style.left = "0px";
    div.style.top = "0px";
    div.style.width = "100px";
    div.style.height = "100px";
    div.style.background = "red";
    div.style.color = "blue";

    div.addEventListener('mousedown', handleKeyPressed, true);

    document.body.appendChild(div);


})();

function handleKeyPressed(event) {

    event.preventDefault();

    mousePosition = {

        x : event.clientX,
        y : event.clientY

    };

    div.style.left = mousePosition.x;
    div.style.top = mousePosition.y;

    //alert("whoa!");

}
javascript html onmousedown
10个回答
106
投票

我想你正在寻找更像这样的东西

var mousePosition;
var offset = [0,0];
var div;
var isDown = false;

div = document.createElement("div");
div.style.position = "absolute";
div.style.left = "0px";
div.style.top = "0px";
div.style.width = "100px";
div.style.height = "100px";
div.style.background = "red";
div.style.color = "blue";

document.body.appendChild(div);

div.addEventListener('mousedown', function(e) {
    isDown = true;
    offset = [
        div.offsetLeft - e.clientX,
        div.offsetTop - e.clientY
    ];
}, true);

document.addEventListener('mouseup', function() {
    isDown = false;
}, true);

document.addEventListener('mousemove', function(event) {
    event.preventDefault();
    if (isDown) {
        mousePosition = {

            x : event.clientX,
            y : event.clientY

        };
        div.style.left = (mousePosition.x + offset[0]) + 'px';
        div.style.top  = (mousePosition.y + offset[1]) + 'px';
    }
}, true);

小提琴


22
投票

支持触摸输入

所有其他答案(包括已接受的答案)不适用于触摸输入。 触摸输入的事件与鼠标输入的事件不同。请参阅 MDN 上的使用触摸事件

以下代码片段即使使用触摸输入也适用。我已经突出显示了需要添加以支持触摸设备的所有代码行。
这里的基本思想是类列表中包含

draggable
的每个元素都应该是可拖动的。当您有大量需要拖动的元素时,这个概念更容易理解。

请参阅 this Glitch 页面和以下演示。

const d = document.getElementsByClassName("draggable");

for (let i = 0; i < d.length; i++) {
  d[i].style.position = "relative";
}

function filter(e) {
  let target = e.target;

  if (!target.classList.contains("draggable")) {
    return;
  }

  target.moving = true;

  //NOTICE THIS 👇 Check if Mouse events exist on users' device
  if (e.clientX) {
    target.oldX = e.clientX; // If they exist then use Mouse input
    target.oldY = e.clientY;
  } else {
    target.oldX = e.touches[0].clientX; // Otherwise use touch input
    target.oldY = e.touches[0].clientY;
  }
  //NOTICE THIS 👆 Since there can be multiple touches, you need to mention which touch to look for, we are using the first touch only in this case

  target.oldLeft = window.getComputedStyle(target).getPropertyValue('left').split('px')[0] * 1;
  target.oldTop = window.getComputedStyle(target).getPropertyValue('top').split('px')[0] * 1;

  document.onmousemove = dr;
  //NOTICE THIS 👇
  document.ontouchmove = dr;
  //NOTICE THIS 👆

  function dr(event) {
    event.preventDefault();

    if (!target.moving) {
      return;
    }
    //NOTICE THIS 👇
    if (event.clientX) {
      target.distX = event.clientX - target.oldX;
      target.distY = event.clientY - target.oldY;
    } else {
      target.distX = event.touches[0].clientX - target.oldX;
      target.distY = event.touches[0].clientY - target.oldY;
    }
    //NOTICE THIS 👆

    target.style.left = target.oldLeft + target.distX + "px";
    target.style.top = target.oldTop + target.distY + "px";
  }

  function endDrag() {
    target.moving = false;
  }
  target.onmouseup = endDrag;
  //NOTICE THIS 👇
  target.ontouchend = endDrag;
  //NOTICE THIS 👆
}
document.onmousedown = filter;
//NOTICE THIS 👇
document.ontouchstart = filter;
//NOTICE THIS 👆
.draggable {
  width: 100px;
  height: 100px;
  background: red;
}
<div class="draggable"></div>


9
投票

检查这是否比adeneo更平滑:FIDDLE

var m = document.getElementById('move');
m.addEventListener('mousedown', mouseDown, false);
window.addEventListener('mouseup', mouseUp, false);

function mouseUp() {
    window.removeEventListener('mousemove', move, true);
}

function mouseDown(e) {
    window.addEventListener('mousemove', move, true);
}

function move(e) {
    m.style.top = e.clientY + 'px';
    m.style.left = e.clientX + 'px';
};

7
投票

我刚刚对 @adeneo 非常有效的答案做了一个小改动。 如果所有内容都包含在函数中,并且每个事件都附加到 div,则可以将其用作库的一部分。

调用以下函数并传递 id。如果 div 不存在,则会创建它。

function drag_div(div_id){
var div;

div = document.getElementById(div_id);

if(div == null){
   div = document.createElement("div");
   div.id = div_id;
   div.style.position = "absolute";
   div.style.left = "0px";
   div.style.top = "0px";
   div.style.width = "100px";
   div.style.height = "100px";
   div.style.background = "red";
   div.style.color = "blue";
   document.body.appendChild(div);
}

div.addEventListener('mousedown', function(e) {
    div.isDown = true;
    div.offset = [
        div.offsetLeft - e.clientX,
        div.offsetTop - e.clientY
    ];
}, true);

div.addEventListener('mouseup', function() {
    div.isDown = false;
}, true);

div.addEventListener('mousemove', function(event) {
    event.preventDefault();
    if (div.isDown) {
        div.mousePosition = {

            x : event.clientX,
            y : event.clientY

        };
        div.style.left = (div.mousePosition.x + div.offset[0]) + 'px';
        div.style.top  = (div.mousePosition.y + div.offset[1]) + 'px';
    }
}, true);
}

2
投票

您可以将其用作图书馆。工作完美。我在 github 上找到了它,但有时会卡住,因为共享者将“mouseup”添加到元素中。我将其更改为文档并解决了问题。这是修复版

'use strict';

/**
 * Makes an element draggable.
 *
 * @param {HTMLElement} element - The element.
 */
function draggable(element) {
    var isMouseDown = false;

    // initial mouse X and Y for `mousedown`
    var mouseX;
    var mouseY;

    // element X and Y before and after move
    var elementX = 0;
    var elementY = 0;

    // mouse button down over the element
    element.addEventListener('mousedown', onMouseDown);

    /**
     * Listens to `mousedown` event.
     *
     * @param {Object} event - The event.
     */
    function onMouseDown(event) {
        mouseX = event.clientX;
        mouseY = event.clientY;
        isMouseDown = true;
    }

    // mouse button released
    document.addEventListener('mouseup', onMouseUp);

    /**
     * Listens to `mouseup` event.
     *
     * @param {Object} event - The event.
     */
    function onMouseUp(event) {
        isMouseDown = false;
        elementX = parseInt(element.style.left) || 0;
        elementY = parseInt(element.style.top) || 0;
    }

    // need to attach to the entire document
    // in order to take full width and height
    // this ensures the element keeps up with the mouse
    document.addEventListener('mousemove', onMouseMove);

    /**
     * Listens to `mousemove` event.
     *
     * @param {Object} event - The event.
     */
    function onMouseMove(event) {
        if (!isMouseDown) return;
        var deltaX = event.clientX - mouseX;
        var deltaY = event.clientY - mouseY;
        element.style.left = elementX + deltaX + 'px';
        element.style.top = elementY + deltaY + 'px';
    }
}

2
投票

这是另一种包括触摸输入的方法。

dragElement(document.getElementById('mydiv'));

function dragElement(element) {
    var startX = 0, startY = 0, endX = 0, endY = 0;
    element.onmousedown = dragStart;
    element.ontouchstart = dragStart;

    function dragStart(e) {
        e = e || window.event;
        e.preventDefault();
        // mouse cursor position at start  
        if (e.clientX) {  // mousemove
            startX = e.clientX;
            startY = e.clientY;
        } else { // touchmove - assuming a single touchpoint
            startX = e.touches[0].clientX
            startY = e.touches[0].clientY
        }
        document.onmouseup = dragStop;
        document.ontouchend = dragStop;
        document.onmousemove = elementDrag;  // call whenever the cursor moves
        document.ontouchmove = elementDrag;
    }

    function elementDrag(e) {
        e = e || window.event;
        e.preventDefault();
        // calculate new cursor position
        if (e.clientX) {
            endX = startX - e.clientX;
            endY = startY - e.clientY;
            startX = e.clientX;
            startY = e.clientY;
        } else {
            endX = startX - e.touches[0].clientX;
            endY = startY - e.touches[0].clientY;
            startX = e.touches[0].clientX;
            startY = e.touches[0].clientY;
        }
        // set the new position
        element.style.left = (element.offsetLeft - endX) + "px";
        element.style.top = (element.offsetTop - endY) + "px";
    }

    function dragStop() {
        // stop moving on touch end / mouse btn is released 
        document.onmouseup = null;
        document.onmousemove = null;
        document.ontouchend = null;
        document.ontouchmove = null;
    }
}

1
投票

jquery 更容易部署。我很惊讶你说你不想学它。

您可以将jquery文件保存在本地计算机中,这样您就不需要互联网 使用 jquery 功能。

就我而言,我已将其保存在工具文件夹中。所以我不需要上网。

对于上面回答的所有 js 多行 js 代码,您只需要一小行。

 <script src="/common/tools/jquery-1.10.2.js"></script>
 <script src="/common/tools/jquery-ui.js"></script>

 <script>
   $(function() {
   $( "#mydiv_to_make_draggable" ).draggable();
   });
</script>

1
投票

接受并添加触摸的答案

adeneo 接受的答案非常优雅并且效果很好。然而它只适用于鼠标点击,所以这里有一个修改版本,其中包括触摸输入:

var position;
var offset = [0,0];
var isDown = false;

function makeDraggable(el){

    ['mousedown', 'touchstart'].forEach( evt => 
        el.addEventListener(evt, pickup, true)
    );
    
    ['mousemove', 'touchmove'].forEach( evt => 
        el.addEventListener(evt, move, true)
    );

    ['mouseup', 'touchend'].forEach( evt => 
        el.addEventListener(evt, drop, true)
    );      
        
    function pickup(e) {
        isDown = true;
        if (e.clientX) {
            offset = [el.offsetLeft - e.clientX, el.offsetTop - e.clientY];
        }
        else if (e.touches) {  
            // for touch devices, use 1st touch only
            offset = [el.offsetLeft - e.touches[0].pageX, el.offsetTop - e.touches[0].pageY];
        }       
    }
    function move(e) {
        if (isDown) {
            if (e.clientX) {
                position = {x : e.clientX, y : e.clientY};
            }
            else if (e.touches) {
                position = {x : e.touches[0].pageX, y : e.touches[0].pageY};            
            }           
            el.style.left = (position.x + offset[0]) + 'px';
            el.style.top  = (position.y + offset[1]) + 'px';
        }
    }
    function drop(e) {
        // seems not to be needed for Android Chrome
        // and modern browsers on Mac & PC
        // but is required for iPad & iPhone
        isDown = false;     
        el.style.left = (position.x + offset[0]) + 'px';
        el.style.top  = (position.y + offset[1]) + 'px';
    }
}

1
投票

聚会迟到了,但是,我发现这是一个更简单且触摸友好的实现:

  • 使用“指针向下/移动/向上”事件
    此外,无需不断监听 mousemove 事件并使用
    isMove
    等布尔值。相反,将 moveup 事件附加到 pointdown 上,并在 pointerup 上使用 Element.removeEventListener 将侦听器与 分离窗户.
  • 使用 CSS
    touch-action: none;
    使指针事件在触摸设备上工作
  • 不要存储拖动开始坐标,而是在元素的当前 Element.offsetLeft/Top 上使用 Event.movementX,Y

const drag = (evt) => {
  
  const el = evt.currentTarget;
  el.style.touchAction = "none";
  
  const move = (evt) => {
    el.style.left = `${el.offsetLeft + evt.movementX}px`;
    el.style.top = `${el.offsetTop + evt.movementY}px`;
  };
  
  const up = () => {
    removeEventListener("pointermove", move);
    removeEventListener("pointerup", up);
  };
  
  addEventListener("pointermove", move);
  addEventListener("pointerup", up);
};


// Use like:
document.querySelector("#box").addEventListener("pointerdown", drag);
#box { position: absolute; width: 50px; height: 50px; background: red; }
<div id="box"></div>


0
投票

.box {
    width: 100px;
    height: 100px;
    background-color: red;
    margin: 10px;
    position: absolute;
}
<!DOCTYPE html>
<html>
<head>
    <title>Playground</title>
    <link rel="stylesheet" type="text/css" href="style.css">
</html>
<body>
    <div class="box">Box 1</div>
</body>

<script>

    let objectSelected = false;

    function selectObject(e) {
        const box = document.querySelector('.box');
        if (e.target === box && !objectSelected) {
            document.addEventListener('mousemove', moveObject);
            document.addEventListener('click', unSelectObject);
            objectSelected = true;
        }
    }

    function unSelectObject(e) {
        const box = document.querySelector('.box');
        if (e.target === box && objectSelected) {
            document.removeEventListener('mousemove', moveObject);
            document.addEventListener('click', selectObject);
            objectSelected = false;
        }
    }

    function moveObject(e) {
        const box = document.querySelector('.box');
        box.style.top = (e.clientY - 50) + 'px';
        box.style.left = (e.clientX - 50) + 'px';
    }

    function setEvents() {
        document.addEventListener('click', selectObject);
    }
    
    setEvents();
    

</script>
</html>

© www.soinside.com 2019 - 2024. All rights reserved.