如何使用InteractJs使可拖动元素跟随触摸移动坐标上的光标

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

我在容器内有一个可拖动元素,并且仅限于其边界。我使用 InteractJs 来实现这一点。可拖动元素默认隐藏,并在触摸开始时变得可见。

但是我想让可拖动元素跟随用户的光标/触摸位置,以便它可以出现在第一个用户单击/触摸的位置的正下方,然后在拖动/触摸移动时跟随它并在触摸结束时消失。

您能否告诉我如何修改我的代码以实现这种行为?我尝试将

transform
样式属性与 touchstart 的坐标一起应用,但没有成功。

示例: https://codepen.io/moogeek/pen/oNQWwaN

<!DOCTYPE html>
<html>
   <head>
      <title></title>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.10.17/interact.min.js"></script>
      <style>
         body{padding-top:100px;}
         .container {
         width:368px;
         height:120px;
         background-color:red;
         margin:0 auto;
         z-index:2
         }
         .draggable {
         visibility:hidden;
         height:60px;
         width:80px;
         background-color:#fff;
         display:inline-block;
         touch-action:none;
         z-index:1;
         }
      </style>
   </head>
   <body>
      <div class="container">
         <div class="draggable"></div>
      </div>
   </body>
</html>

js:

let dragMoveListener=(event) => {
 let draggable=document.getElementsByClassName("draggable")[0],
     target = event.target,
  // keep the dragged position in the data-x/data-y attributes
  x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
  y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;

  draggable.style.visibility='visible';
  target.style.backgroundPosition=x + 'px ' + y + 'px';
  target.style.webkitTransform = target.style.transform
                               = 'translate(' + x + 'px, ' + y + 'px)';
  // update the posiion attributes
  target.setAttribute('data-x', x);
  target.setAttribute('data-y', y);
}

let draggables=document.querySelectorAll(".draggable"),
    containers=document.querySelectorAll(".container");

    containers.forEach(function(element){
        interact(element).on("tap down",function(e){
            var wt=element.querySelector('.draggable');
            var wect=wt.getBoundingClientRect();
            wt.style.visibility='visible';

       });
    });

    draggables.forEach(function(element){
        interact(element)
        .on("dragstart",function(e){
            var x=element.getAttribute("data-x");
            var y=element.getAttribute("data-y");
            if(x!=null && y!=null){
                //draggable.webkitTransform = draggable.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
            }
        }).
        on("dragmove",function(e){
        })
        .on("dragend",function(e){
            element.style.visibility='hidden';
            //draggable.webkitTransform = draggable.style.transform = 'translate(0px, 0px)';
        }).draggable({
        onmove: dragMoveListener,
        modifiers: [
                interact.modifiers.restrict({
                restriction: 'parent',
                endOnly: false
                })
        ]})
    });
javascript draggable touch-event interactjs
2个回答
1
投票

要实现这一目标,你可以尝试这个。

  1. 在容器元素内添加一个具有“follower”类的新元素。该元素将充当跟随者元素。
  2. 在容器点击/按下时,将跟随者元素的位置设置为用户单击/触摸的位置并使其可见。
  3. 在容器dragmove上,更新follower元素的位置,以便可拖动元素在拖动时可以跟随它。
  4. 在容器拖尾上,隐藏跟随者元素并重置其位置。

请参阅下面的演示

    let dragMoveListener = (event) => {
      let draggable = document.querySelector(".draggable"),
          follower = document.querySelector(".follower"),
          target = event.target,
          x = event.clientX,
          y = event.clientY;

      follower.style.visibility = 'visible';
      follower.style.transform = 'translate(' + x + 'px, ' + y + 'px)';

      target.style.backgroundPosition = x + 'px ' + y + 'px';
    };

    let containers = document.querySelectorAll(".container");

    containers.forEach(function (element) {
      interact(element).on("tap down", function (e) {
        var wt = element.querySelector('.draggable');
        var wect = wt.getBoundingClientRect();
        var follower = element.querySelector('.follower');

        // Set the position of the follower element to the position of the user's click/touch
        var x = e.clientX - wect.left;
        var y = e.clientY - wect.top;
        follower.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
        follower.style.visibility = 'visible';
      });
    });

    containers.forEach(function (element) {
      interact(element)
        .on("dragstart", function (e) {
          var x = element.getAttribute("data-x");
          var y = element.getAttribute("data-y");
          if (x != null && y != null) {
            //draggable.webkitTransform = draggable.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
          }
        })
        .on("dragmove", dragMoveListener)
        .on("dragend", function (e) {
          var draggable = document.querySelector(".draggable");
          var follower = document.querySelector(".follower");
          draggable.style.visibility = 'hidden';
          follower.style.visibility = 'hidden';
          //draggable.webkitTransform = draggable.style.transform = 'translate(0px, 0px)';
        })
        .draggable({
          onmove: dragMoveListener,
          modifiers: [
            interact.modifiers.restrict({
              restriction: 'parent',
              endOnly: false
            })
          ]
        });
    });
  
    .container {
      width: 300px;
      height: 300px;
      position: relative;
      background-color: red;
    }

    .draggable {
      width: 100px;
      height: 100px;
      background-color: #fff;
      color: white;
      text-align: center;
      line-height: 100px;
      user-select: none;
      cursor: move;
      position: absolute;
      top: 0;
      left: 0;
      visibility: hidden;
    }

    .follower {
      width: 100px;
      height: 100px;
      background-color: #fff;
      opacity: 1;
      position: absolute;
      top: 0;
      left: 0;
      visibility: hidden;
    }
<!DOCTYPE html>
<html>
<head>
  <title>Draggable Element</title>
</head>
<body>
  <div class="container">
    <div class="draggable">Draggable Element</div>
    <div class="follower"></div>
  </div>

  <script src="https://unpkg.com/interactjs"></script>  
</body>
</html>

JSBIN 演示


1
投票

我已经修改了您的代码来执行您正在寻找的操作,但我建议您可以在普通的 JavaScript 中实现相同的结果,这将消除使用库的开销。请参阅MDN 拖放

此外,如果您要拥有此示例的多个实例,您可能应该使用

event.target
而不是全局变量。

JS

let dragMoveListener = (event) => {
  let draggable = document.getElementsByClassName("draggable")[0],
    target = event.target,
    // keep the dragged position in the data-x/data-y attributes
    x = (parseFloat(target.getAttribute("data-x")) || 0) + event.dx,
    y = (parseFloat(target.getAttribute("data-y")) || 0) + event.dy;

  //draggable.style.visibility = "visible";
  target.style.backgroundPosition = x + "px " + y + "px";
  target.style.webkitTransform = target.style.transform =
    "translate(" + x + "px, " + y + "px)";
  // update the posiion attributes
  target.setAttribute("data-x", x);
  target.setAttribute("data-y", y);
};

let draggables = document.querySelectorAll(".draggable"),
  containers = document.querySelectorAll(".container");

containers.forEach(function (element) {
  interact(element).on("tap down", function (e) {
    const dragElem = element.querySelector(".draggable");
    const dragBCR = dragElem.getBoundingClientRect();
    const contBCR = element.getBoundingClientRect();
    if (
      dragBCR.left < e.x && e.x < dragBCR.right &&
      dragBCR.top < e.y && e.y < dragBCR.bottom &&
      !( contBCR.top == dragBCR.top && contBCR.left == dragBCR.left )
    ) return true;
    dragElem.setAttribute("data-x", e.x - contBCR.x);
    dragElem.setAttribute("data-y", e.y - contBCR.y);
    dragMoveListener({ target: dragElem, dx: 0, dy: 0 });
    dragElem.style.visibility = "visible";
  });
});

draggables.forEach(function (element) {
  interact(element)
    .on("dragstart", function (e) {
      var x = element.getAttribute("data-x");
      var y = element.getAttribute("data-y");
      if (x != null && y != null) {
        //draggable.webkitTransform = draggable.style.transform = 'translate(' + x + 'px, ' + y + 'px)';
      }
    })
    .on("dragmove", function (e) {})
    .on("dragend", function (e) {
      const contElem = element.closest(".container");
      const contBCR = contElem.getBoundingClientRect();
      element.style.visibility = "hidden";
      element.setAttribute("data-x", 0);
      element.setAttribute("data-y", 0);
      dragMoveListener({ target: element, dx: 0, dy: 0 });
    })
    .draggable({
      onmove: dragMoveListener,
      modifiers: [
        interact.modifiers.restrict({
          restriction: "parent",
          endOnly: false
        })
      ]
    });
});
© www.soinside.com 2019 - 2024. All rights reserved.