如何使用javascript欺骗拖动同一类的所有元素?

时间:2015-01-30 00:31:24

标签: javascript mousemove dom-events

我试图制作它,以便当用户按住鼠标按钮然后拖动鼠标时会移动一堆元素。我试图通过听mousedown和mousemove事件并比较它们的位置来做到这一点。位置的差异用于计算移动所有元素的距离。目标是感觉所有元素都被拖动了。但是出于某种原因,我的方法会导致元素飞到各处。

以下是我尝试做的一个例子:

window.onload = function(){
    var mouse = {isDown : false, lastX : null, lastY : null }; 

    document.body.addEventListener("click", function(event){
        var el = document.createElement("div"); 
        el.className = "box"; 
        el.style.left = event.clientX + "px"; 
        el.style.top = event.clientY + "px"; 
        el.style.backgroundColor = "BLACK";
        el.style.width = "16px";
        el.style.height = "16px";  
        el.style.position = "absolute"; 
        document.body.appendChild(el); 
    });

    document.body.addEventListener("mousedown", function(event){
        mouse.isDown = true; 
        mouse.lastX = event.clientX; 
        mouse.lastY = event.clientY; 
    });

    document.body.addEventListener("mouseup", function(){
        mouse.isDown = false; 
        mouse.lastX = null; 
        mouse.lastY = null; 
    }); 

    var removePx = function(string){return string.substring(0, string.length -2);}  

    document.body.addEventListener("mousemove", function(event){
        console.log("move (" + event.clientX + "," + event.clientY + ")"); 

        if(mouse.isDown){
            var deltaX = event.clientX - mouse.lastX; 
            var deltaY = event.clientY - mouse.lastY; 

            console.log("DeltaX " + deltaX); 
            console.log("DeltaY " + deltaY); 

            var boxes = document.getElementsByClassName("box"); 
            for(var i = 0; i<boxes.length; i++){
                var box = boxes[i];
                box.style.left = removePx(box.style.left) + deltaX + "px"; 
                box.style.top = removePx(box.style.top) + deltaY + "px"; 
            }

            mouse.lastX = event.clientX; 
            mouse.lastY = event.clientY; 
        }

    });
}

这里出了什么问题?还有,有更好的方法来实现这一目标吗?

1 个答案:

答案 0 :(得分:1)

关于您的代码,我会说transform对于此类事物(而不是左/上)的定位更受欢迎 - 请参阅讨论http://www.paulirish.com/2012/why-moving-elements-with-translate-is-better-than-posabs-topleft/

无论如何,我没有仔细查看你的代码,而是自己尝试了解我所理解的内容。我只使用了一个关于拖放的简单模式:

  1. onmousedown - setState移动,存储点击的点,获取当前应用的转换矩阵
  2. onmousemove - 计算dx,dy,累积矩阵中的差异,更新状态中的当前x和y
  3. onmouseup - 只需删除移动状态
  4. 这是一个片段:

    var main = document.querySelector('main');
    var movable = [].slice.call(document.querySelectorAll('.movable'));
    var _state = {
      x: 0,
      y: 0,
      matrix: [1, 0, 0, 1, 0, 0],
      moving: false
    };
    
    movable.forEach(function (elem) {
      elem.style.transform = 'matrix(' + _state.matrix.join(',') + ')'
    });
    
    function onMouseDown (e) {
      _state.moving = true;
      _state.x = e.clientX;
      _state.y = e.clientY;
      _state.matrix = matrixToArray(e.target.style.transform);
    }
    
    function matrixToArray (matrix) {
      return matrix
          .match(/matrix\((.*)\)/)[1]
          .split(' ')
          .join('')
          .split(',')
          .map(function (a) {
            return +a;
          });
    }
    
    function onMouseMove (e) {
      if (!_state.moving)
        return;
    
      var dx = e.clientX - _state.x;
      var dy = e.clientY - _state.y;
    
      _state.matrix[4] += dx;
      _state.matrix[5] += dy;
    
      var transf = 'matrix(' + _state.matrix.join(',') + ')'
    
      movable.forEach(function (elem) {
        elem.style.transform = transf;
      });
    
      _state.x = e.clientX;
      _state.y = e.clientY;
    }
    
    function onMouseUp (e) {
      _state.moving = false;
      _state.x = e.clientX;
      _state.y = e.clientY;
    }
    
    main.addEventListener('mousemove', onMouseMove);
    main.addEventListener('mouseup', onMouseUp);
    
    movable.forEach(function (elem) {
      elem.addEventListener('mousedown', onMouseDown);
    });
    html,
    body,
    main {
      width: 100%;
      height: 100%;
    }
    
    div {
      width: 50px;
      height: 50px;
      position: absolute;
    }
    
    #d1 { background: black; left: 10px; top: 10px;}
    #d2 { background: brown; left: 70px; top: 10px;}
    #d3 { background: green; left: 10px; top: 70px ;}
    #d4 { background: purple; left: 70px; top: 70px ;}
    <main>
      <div id="d1" class="movable"></div>
      <div id="d2" class="movable"></div>
      <div id="d3" class="not-movable"></div>
      <div id="d4" class="movable"></div>
    </main>

    ps:这不是那么有效率。人们可以肯定地重复这个并创建一个更好的版本!