下面是用来模拟拖放效果的.我正在使用Object.assign(target.style, ...)手动更改mousedownmouseup事件的样式.如果我用包含mousedown个样式的.dragging个类替换赋值语句,然后删除mouseup上的那个类,则在删除.dragging个类之后,mouseup中设置的关联的lefttop属性将保持不变.

以下是工作版本:

(function() {
    let targets = document.querySelectorAll('.draggable');
    let offsetX;
    let offsetY;
    targets.forEach((target) => {
        target.isMouseDown = false;
        target.initialOffsetLeft = target.offsetLeft;
        target.initialOffsetTop = target.offsetTop;
        target.addEventListener('mousedown', (e) => {
            if (e.buttons === 1) {
                Object.assign(target.style, {
                    transition: null,
                    zIndex: 10000,
                    position: 'relative'
                });
                target.isMouseDown = true;
                offsetX = target.initialOffsetLeft + e.offsetX;
                offsetY = target.initialOffsetTop + e.offsetY;
            }
        });
        document.addEventListener('mouseup', (e) => {
            e.preventDefault();
            target.isMouseDown = false;
            Object.assign(target.style, {
                transition: 'all 0.5s ease',
                zIndex: null,
                left:  '0',
                top: '0'
            });
        });
        document.addEventListener('mousemove', (e) => {
            e.preventDefault();
            if (target.isMouseDown) {
                target.style.left = e.pageX - offsetX + 'px';
                target.style.top = e.pageY - offsetY + 'px';
            }
        });
    });
})();
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Roboto', sans-serif
}

.draggable {
  display: flex;
  padding: 10px 12px;
  margin-top: 0px;
  margin-left: 0px;
  margin-bottom: 11px;
  border-radius: 5px;
  margin-right: 5px;
  background-color: #000000;
  cursor: grab;
  flex-grow: 1;
  color: #ffffff;
  border: 1px solid #6c757d;
}

.my-card-group {
  margin-top: 30px;
  background-color: #000000;
  margin-right: 2%;
  margin-left: 2%;
  border: 1px solid #6c757d;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<div class="card group">
  <div class="my-card-group">
    <div class="card-body">
      <div class="draggable">
        Lorem ipsum dolor sit amet 1
      </div>
      <div class="draggable">
        Lorem ipsum dolor sit amet 2
      </div>
      <div class="draggable">
        Lorem ipsum dolor sit amet 3
      </div>
    </div>
  </div>
</div>

下面是我用.dragging个类替换Object.assign(...)条语句的方法:

(function() {
    let targets = document.querySelectorAll('.draggable');
    let offsetX;
    let offsetY;
    targets.forEach((target) => {
        target.isMouseDown = false;
        target.initialOffsetLeft = target.offsetLeft;
        target.initialOffsetTop = target.offsetTop;
        target.addEventListener('mousedown', (e) => {
            if (e.buttons === 1) {
                target.classList.add('dragging')  // replaced with this
                target.isMouseDown = true;
                offsetX = target.initialOffsetLeft + e.offsetX;
                offsetY = target.initialOffsetTop + e.offsetY;
            }
        });
        document.addEventListener('mouseup', (e) => {
            e.preventDefault();
            target.isMouseDown = false;
            target.classList.remove('dragging') // replaced with this
        });
        document.addEventListener('mousemove', (e) => {
            e.preventDefault();
            if (target.isMouseDown) {
                target.style.left = e.pageX - offsetX + 'px';
                target.style.top = e.pageY - offsetY + 'px';
            }
        });
    });
})();
 

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Roboto', sans-serif
}

.draggable {
    display: flex;
    padding: 10px 12px;
    border-radius: 5px;
    margin: 0 5px 11px 0;
    background-color: #000000;
    cursor: grab;
    flex-grow: 1;
    color: #ffffff;
    border: 1px solid #6c757d;
    transition: all 0.5s ease; /*added this*/
    z-index: unset; /*added this*/
    left: 0; /*added this*/
    top: 0 /*added this*/
}

.dragging { /*added this*/
    z-index: 10000;
    position: relative;
    transition: all 0s;
}

.my-card-group {
    margin-top: 30px;
    background-color: #000000;
    margin-right: 2%;
    margin-left: 2%;
    border: 1px solid #6c757d;
}
 
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<div class="card group">
  <div class="my-card-group">
    <div class="card-body">
      <div class="draggable">
        Lorem ipsum dolor sit amet 1
      </div>
      <div class="draggable">
        Lorem ipsum dolor sit amet 2
      </div>
      <div class="draggable">
        Lorem ipsum dolor sit amet 3
      </div>
    </div>
  </div>
</div>

这打破了拖动的工作方式,因为lefttop以及transition属性在移除.dragging之后仍然存在,下一次拖动.draggable中的任何属性时,它将从上一次拖动结束的位置开始,并具有设置为.dragging的过渡延迟.有没有一种方法可以使用类似的方法来实现初始行为?

推荐答案

请参见代码注释.

(function() {
  let targets = document.querySelectorAll('.draggable');
  targets.forEach((target) => {
    let offsetX;
    let offsetY;
    target.isMouseDown = false;
    target.initialOffsetLeft = target.offsetLeft;
    target.initialOffsetTop = target.offsetTop;
    target.addEventListener('mousedown', (e) => {
      if (e.button == 0) {
        // moved preventDefault, to not trigger on rclick or auxclick
        e.preventDefault();
        // clean start, it can appear that resetting is still present,
        // during the animation when you regrab it within the animation duration
        target.classList.remove("resetting");
        target.style.left = target.style.top = "0px";
        
        target.classList.add('dragging') // replaced with this
        target.isMouseDown = true;
        offsetX = target.initialOffsetLeft + e.offsetX;
        offsetY = target.initialOffsetTop + e.offsetY;
      }
    });
    document.addEventListener('mouseup', (e) => {
      // added check if the targets mouse is down
      // this is required as you listen on the whole document
      // also it won't trigger anymore if right mouseup is fired
      if (target.isMouseDown && e.button == 0) {
        e.preventDefault();
        target.isMouseDown = false;
        target.classList.remove('dragging');

        // adds the "move back" animation from the first example
        target.classList.add("resetting");

        // removes everything again that was when the transition effect ended
        target.addEventListener("transitionend", () => {
          Object.assign(target.style, { top: "", left: "" });
          target.classList.remove("resetting");
        }, { once: true });
      }
    });
    document.addEventListener('mousemove', (e) => {
      // moved preventDefault() inside the condition to prevent unwanted behavior on other scripts, as you listen on the whole document
      if (target.isMouseDown) {
        e.preventDefault();  
        target.style.left = e.pageX - offsetX + 'px';
        target.style.top = e.pageY - offsetY + 'px';
      }
    });
  });
})();
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
    font-family: 'Roboto', sans-serif
}

.draggable {
    display: flex;
    padding: 10px 12px;
    border-radius: 5px;
    margin: 0 5px 11px 0;
    background-color: #000000;
    cursor: grab;
    flex-grow: 1;
    color: #ffffff;
    border: 1px solid #6c757d;
}
/* This removes the animation during dragging */
.draggable:not(.dragging) {
    transition: all 0.5s ease;
    left: 0px;
    top: 0px;
}
/* this allows the animation to play from the current position back to 0,0 */
.draggable.resetting {
    z-index: 10000;
    top: 0px!important;
    left: 0px!important;
    position: relative;
}
.draggable.dragging {
    z-index: 10000;
    position: relative;
}

.my-card-group {
    margin-top: 30px;
    background-color: #000000;
    margin-right: 2%;
    margin-left: 2%;
    border: 1px solid #6c757d;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" />
<div class="card group">
  <div class="my-card-group">
    <div class="card-body">
      <div class="draggable">
        Lorem ipsum dolor sit amet 1
      </div>
      <div class="draggable">
        Lorem ipsum dolor sit amet 2
      </div>
      <div class="draggable">
        Lorem ipsum dolor sit amet 3
      </div>
    </div>
  </div>
</div>

Javascript相关问答推荐

JavaScript代理不适用于打开的窗口对象

带对角线分隔符的图像滑动器

使用typeof运算符获取对象值类型-接收字符串而不是数组

一次仅播放一个音频

如何修复内容安全策略指令脚本-SRC自身错误?

如何在使用fast-xml-parser构建ML时包括属性值?

Redux工具包查询(RTKQ)端点无效并重新验证多次触发

Plotly热图:在矩形上zoom 后将zoom 区域居中

在react JS中映射数组对象的嵌套数据

制作钢琴模拟器,并且在控制台中不会执行或显示该脚本

WhatsApp Cloud API上载问题:由于MIME类型不正确而导致接收&Quot;INVALID_REQUEST";错误

Angular 形式,从DOM中删除不会删除指定索引处的内容,但会删除最后一项

查询参数中的JAVASCRIPT/REACT中的括号

覆盖加载器页面避免对页面上的元素进行操作

使用带有HostBinding的Angular 信号来更新样式?

如何使用JS创建一个明暗功能按钮?

<;img>;标记无法呈现图像

无法检索与Puppeteer的蒸汽游戏的Bundle 包价格

我正在试着做一个TicTacToe Ai来和我玩.但是,我试着在第一个方块被点击时出现一个X,然后在第二个方块之后出现一个O

Clip-Path在网页浏览器(Mozilla、Edge、Chrome)上不能正常工作,但在预览版Visual Code Studio HTML、CSS、JS上却能很好地工作