自定义拖动元素跳转

Custom drag element jumps around

提问人: 提问时间:1/24/2021 更新时间:1/24/2021 访问量:443

问:

显然,我对鼠标光标和元素偏移的数学做了一些卡顿的事情,但我无法弄清楚是什么。为什么元素会跳得这么厉害?目标是能够拖动元素,但我需要它相对于鼠标保持(IE 而不是 SNAP 到光标)。此外,我实际上希望能够使用父元素进行拖动,如果这有意义的话,如代码中所示。您可以“拖动”父容器来移动目标。

此外,我意识到还有其他问题需要改进(例如拖出页面等),但此问题的目的是解决来回跳转的问题。

let scaleX = 1;
let scaleY = 1;
let skewX = 0;
let skewY = 0;
let translateX = 0;
let translateY = 0;
let isPanning = false;

let $map = $('#map');
let $container = $('#mapCanvas');

function moveMap() {
    $("#map").css({
        transform: ` matrix(${scaleX}, ${skewX}, ${skewY}, ${scaleY}, ${translateX}, ${translateY})`
    });
}


$container.on("mousedown", function(event) {
  isPanning = true;
});
$container.on("mouseup", function(event) {
    isPanning = false;
});
$container.on("mousemove", function(event) {
    if (isPanning) {
        translateX = event.pageX + (event.pageX - $map.offset().left) ;
        translateY = event.pageY + (event.pageY - $map.offset().top);
        moveMap();
    }
});
#mapCanvas {
  position: absolute;
  left: 0;right:0;top:0;bottom:0;
  user-select: none;
}

#map {
  width: 100px;
  height: 100px;
  text-align: center;
  line-height: 100px;
  border: 1px solid black;
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="mapCanvas">
    <div id="map">DRAG ME</div>
</div>

jQuery 数学 MouseEvent 拖动

评论


答:

1赞 Louys Patrice Bessette 1/24/2021 #1

我敢肯定你先看了这个片段......如果没有,那么现在就去做吧!

那么你的代码出了什么问题呢?

mousemove 是一个“Machinegun”事件。
它像地狱一样开火!因此,在触发事件后,您必须更新全局变量,然后调用函数...与此同时,已经再次开火了......完全搞砸了计算。对于浏览器来说,毫秒是十进制(我一点也不夸张......
moveMapmousemove

若要避免计时问题,只需将事件传递给函数即可。或者只是将函数直接放在事件处理程序中。为什么无论如何都需要一个不同的命名函数?

第二件事...您必须知道鼠标相对于可拖动元素的位置,才能获得所需的平滑拖动效果。计算中使用的元素的位置是左上角。但也许鼠标在“dragStart”的右下角附近......你必须知道。而这只能从事件中扣除。mousedown

享受拖拽的乐趣!

let scaleX = 1;
let scaleY = 1;
let skewX = 0;
let skewY = 0;
//let translateX = 0;   // No need to be global
//let translateY = 0;
let isPanning = false;

// Additional object to store the mouse "offset" versus the element position
let mouse_vs_element;

let $map = $('#map');
let $container = $('#mapCanvas');


function moveMap(event) {
  
  let translateX = event.pageX - mouse_vs_element.X
  let translateY = event.pageY - mouse_vs_element.Y
  //console.log(translateX, translateY)

  $("#map").css({
    transform: ` matrix(${scaleX}, ${skewX}, ${skewY}, ${scaleY}, ${translateX}, ${translateY})`
  });
}

$container.on("mousedown", function(event) {
  isPanning = true;
  
  // Get the draggable element position at start
  let element_pos = event.target.getBoundingClientRect()
  
  // Mouse position relative to that element
  mouse_vs_element = {
    X: event.pageX - element_pos.left,
    Y: event.pageY - element_pos.top
  }
});

$container.on("mouseup", function(event) {
  isPanning = false;
  
  // Clear that (optionnal in fact, but a good practice)
  mouse_vs_element = {}
});

$container.on("mousemove", function(event) {
  if (isPanning) {
    moveMap(event);
  }
});
#mapCanvas {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  user-select: none;
}

#map {
  width: 100px;
  height: 100px;
  text-align: center;
  line-height: 100px;
  border: 1px solid black;
  color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<div id="mapCanvas">
  <div id="map">DRAG ME</div>
</div>

评论

0赞 1/24/2021
谢谢。看起来很棒。但是,如果它们是全局的,如果我需要从其他功能(例如缩放)进行设置怎么办?这就是我在全球范围内跟踪所有变量的原因。建议?显然,我不是专业的程序员......transform
1赞 Louys Patrice Bessette 1/24/2021
那好吧。。。。如果您在其他地方需要,请将它们保持在全局。但是在函数中设置它们(和)。translateXtranslateXYmoveMap