开门就遇见一个bug。。

window.onload = () => {
  const draggable = document.getElementById("draggable");
  draggable.addEventListener("dragstart", handleDragstart);
  let distanceX = 0;
  let distanceY = 0;
  function handleDragstart(e) {
    //获取鼠标位置
    const x = e.clientX;
    const y = e.clientY;
    console.log(x, y);
    //获取draggable的位置
    const offsetX = e.target.offsetLeft;
    const offsetY = e.target.offsetTop;
    console.log(offsetX, offsetY);
    //保存鼠标悬停处与draggable边界的距离(是全局变量)
    distanceX = x - offsetX;
    distanceY = y - offsetY;
    console.log(distanceX, distanceY);
  draggable.addEventListener("drag", handleDrag);
  function handleDrag(e) {
    //获取实时鼠标位置
    let x = e.clientX;
    let y = e.clientY;
    console.log(x, y);
    // 计算出draggable的坐标
    let left = x - distanceX;
    let top = y - distanceY;
    console.log(left, top);
    // //设置draggable坐标
    draggable.style.left = left + "px";
    draggable.style.top = top + "px";

结果一松手就弹到左上角
在这里插入图片描述
查看控制台,哦,原来是
在这里插入图片描述
在拖拽鼠标松开的一瞬间,鼠标坐标e.clientX和Y都变成了0,导致计算left和top时变成了负数,所以一松手就弹到左上角了。趁我没注意啊,我大意了啊。
在这里插入图片描述

然后我想通过百度去找寻答案,结果因为问题难以描述所以没有找到答案,否则有解决方案了我也就懒得写文章了。

大家学过drag事件群就知道,拖拽事件中还有个dragend事件,我尝试添加dragend事件监听

draggable.addEventListener("dragend", handleDragend);
  function handleDragend(e) {
    //获取实时鼠标位置
    let x = e.clientX;
    let y = e.clientY;
    console.log(x, y);

结果正确打印出松手一瞬间的鼠标坐标
在这里插入图片描述
尝试在dragend再次修改一次坐标

draggable.addEventListener("dragend", handleDragend);
  function handleDragend(e) {
    //获取实时鼠标位置
    let x = e.clientX;
    let y = e.clientY;
    console.log(x, y);
    // 计算出draggable的坐标
    let left = x - distanceX;
    let top = y - distanceY;
    // //设置draggable坐标
    draggable.style.left = left + "px";
    draggable.style.top = top + "px";

在这里插入图片描述
不考虑复杂情况,问题在这里已经解决了。

虽然动画很流畅,也没有一瞬间闪到左上角的情况,但是实际上元素的确经过左上角
是弹回去后再过来,我可以用一个触发器来验证

if (draggable.offsetLeft < 0) {
      draggable.style.backgroundColor = "#ff0055"

在这里插入图片描述
为了避免隐患,之后可能会进行一些边界判断,所以我使用了个笨方法(如果有懂为什么松手鼠标坐标会变成0的同学可以在评论区告诉我)

在之前的handleDrag函数(“drag”拖拽事件)中添加if判断。(这样设置一举两得,既可以避免元素弹回左上角,还能让元素不超过边界)

// //设置draggable坐标
    if (left < 0 || top < 0) {
      return;
    draggable.style.left = left + "px";
    draggable.style.top = top + "px";

在这里插入图片描述
虽然问题解决了,但还是不难看出一个问题,不流畅啊!!!
那是因为一碰到边界就阻止设置元素坐标了,如果x轴碰到边界,y轴上也无法移动了。
所以我们分开判断,将前面的改写成

// //设置draggable坐标
    if (left >= 0) {
      draggable.style.left = left + "px";
    if (top >= 0) {
      draggable.style.top = top + "px";

在这里插入图片描述
问题虽然解决了,但还是不难发现一个问题,当快速拖拽超出屏幕时,元素无法贴上边界,这里就是之前各位肯定听教程讲过的“吸边“:
当元素超过边界时,手动将其坐标设置为边界值
为了方便,我先计算出右边边界和下面边界的值

  const maxTop = document.body.clientHeight - draggable.offsetHeight;
  console.log(maxTop);
  const maxLeft = document.body.clientWidth - draggable.offsetWidth;
  console.log(maxLeft);

然后将前面的代码替换成如下

  // //设置draggable坐标
    if (left >= maxLeft) { //当超过右边界
      draggable.style.left = maxLeft + "px";
    } else if (left < 0) { //当超过左边界
      draggable.style.left = "0px";
    } else {
      draggable.style.left = left + "px";
    if (top >= maxTop) { //当超过下边界
      draggable.style.top = maxTop + "px";
    } else if (top < 0) { //当超过上边界
      draggable.style.top = "0px"
    } else {
      draggable.style.top = top + "px"

那么问题就这样解决了。

相信跟着我做的同学一定发现了一个问题

在这里插入图片描述
这是怎么回事?发生甚磨事了?
我一看,哦,原来是:
maxTop = document.body.clientHeight - draggable.offsetHeight 等于 0 了
在这里插入图片描述
问题原因很简单,我没有在div外面套一层全屏容器,导致当前的body高度和div高度相同,也就是说body完全由div撑开其高度。
解决办法很简单,外面套一层全屏容器或者把body的宽高都改成100vh / 100vw就ok了

body {
  width: 100vw;
  height: 100vh;

但你以为这就解决问题了吗?在这里插入图片描述
做到这里虽然还能通过修改代码做一部分改进,但是我已经不想改了,为什么?

因为一旦拖拽元素的鼠标指针超过浏览器边界,就会立刻像之前松开鼠标一样直接弹回左上角,如果说我可以再次通过判断鼠标超出浏览器来阻止触发坐标修改为(0,0)从而阻止其弹回左上角。但是我们已经做了很多步骤了,相同的实现方法有通过mousemove事件实现同样的功能简单而且没有bug,那为什么还要通过drag事件来实现拖拽移动呢?

完整代码贴出:

window.onload = () => {
  const draggable = document.getElementById("draggable");
  draggable.addEventListener("dragstart", handleDragstart);
  let distanceX = 0;
  let distanceY = 0;
  const maxTop = document.body.clientHeight - draggable.offsetHeight;
  console.log(maxTop);
  const maxLeft = document.body.clientWidth - draggable.offsetWidth;
  console.log(maxLeft);
  function handleDragstart(e) {
    //获取鼠标位置
    const x = e.clientX;
    const y = e.clientY;
    console.log(x, y);
    //获取draggable的位置
    const offsetX = e.target.offsetLeft;
    const offsetY = e.target.offsetTop;
    console.log(offsetX, offsetY);
    //保存鼠标悬停处与draggable边界的距离(是全局变量)
    distanceX = x - offsetX;
    distanceY = y - offsetY;
    console.log(distanceX, distanceY);
  draggable.addEventListener("drag", handleDrag);
  function handleDrag(e) {
    //获取实时鼠标位置
    let x = e.clientX;
    let y = e.clientY;
    console.log(x, y);
    // 计算出draggable的坐标
    let left = x - distanceX;
    let top = y - distanceY;
    console.log(left, top);
    // //设置draggable坐标
    if (left >= maxLeft) { //当超过右边界
      draggable.style.left = maxLeft + "px";
    } else if (left < 0) { //当超过左边界
      draggable.style.left = "0px";
    } else {
      draggable.style.left = left + "px";
    if (top >= maxTop) { //当超过下边界
      draggable.style.top = maxTop + "px";
    } else if (top < 0) { //当超过上边界
      draggable.style.top = "0px"
    } else {
      draggable.style.top = top + "px"
//添加松手事件判断
  draggable.addEventListener("dragend", handleDragend);
  function handleDragend(e) {
  //检测是否超出左边界(是就变红)
    if (draggable.offsetLeft < 0) {
      draggable.style.backgroundColor = "#ff0055"
    //再次调用一次拖拽处理函数,把元素从左上角拉回来
    handleDrag(e);

不推荐使用drag进行元素拖拽移动的原因

因此,我总结了几条不推荐使用drag来做元素拖拽移动原因:
1.动画不流畅有明显残影,drag拖拽帧率很低(对比mousemove就能明显发现)
2.在松手的一瞬间会将鼠标位置设置为(0,0)从而导致元素弹回左上角
3.当拖拽离开浏览器时,元素仍然弹回左上角,鼠标坐标变成(0,0),(但事件没有中断)

所以以后遇到这类问题还是老老实实用mouseover来实现吧

项目场景:最近做Uniapp项目,从服务器请求json数据时,console.log打印出的对象中有部分数据字段缺失问题描述:这是服务器的数据,总共包含六个字段这个是控制台打印出的结果,少两个字段不说,连sex字段都错了下面是代码:下拉刷新请求网络数据,而两个url都是一样(我直接复制的)onPullDownRefresh() { uni.request({ url:this.url, success:(res)=&gt; { console.log(re
其实HTML5就是新增一些有用的API让我们更轻松的开发从而把更多精力都放在业务逻辑上来这些API的使用也非常简单不过我的记性不太好所以还是以博客的形式记录下来(手动滑稽)今天就来写一下这个拖拽API说起拖放,其实最早实现拖放功能的还是IE(IE4)H5就是在IE实例的基础上指定的拖拽规范在浏览器中,是有默认拖拽的比如说图片的拖拽选中文本的拖拽链接的拖拽浏览器默认允许我们拖拽图像、文本以及链接让其它元素被拖动也是可以实现的只需要在元素标签上添加一个属性当拖拽这个元素的时候,浏览器就会以半透明复本的方式显示拖拽事件应该分为两类一类是被拖拽元素触发的事件另一类是拖放目标元素触发的事件拖拽元素的时候
在拖放的过程中会触发以下事件: ondragover、ondrop在写回调时须添加: 默认情况下,数据/元素不能在其他元素中被拖放。对于drop我们必须防止元素的默认处理 e.preventDefault(); e.stopPropagation(); 在拖动目标上触发事件 (源元素):
拖拉(drag)指的是,用户在某个对象上按下鼠标键不放,拖动它到另一个位置,然后释放鼠标键,将该对象放在那里。 拖拉的对象有好几种,包括元素节点、图片、链接、选中的文字等等。在网页中,除了元素节点默认不可以拖拉,其他(图片、链接、选中的文字)都是可以直接拖拉的。为了让元素节点可拖拉,可以将该节点的draggable属性设为true。 <div draggable="true"&g...
拖拉(drag)指的是,用户在某个对象上按下鼠标键不放,拖动它到另一个位置,然后释放鼠标键,将该对象放在那里。 拖拉的对象有好几种,包括元素节点、图片、链接、选中的文字等等。在网页中,除了元素节点默认不可以拖拉,其他(图片、链接、选中的文字)都是可以直接拖拉的。为了让元素节点可拖拉,可以将该节点的draggable属性设为true。 &amp;lt;div draggable=&quot;true&quot;&amp;gt;
在没有drag事件的时候,做元素拖拽使用的都是mouse事件,但mouse在处理过程中可能有这样或那样的问题,主要还是感觉不流畅,如果小伙伴们不在考虑低版本IE(<IE9)的话,可以偿试一下drag,会有意想不到的收获。。 下面来展示下drap的主要事件 在拖动目标上触发事件 (源元素): ondragstart - 用户开始拖动元素时触发 ondrag - 元素正在拖动时触发 ondragend - 用户完成元素拖动后触发 释放目标时触发的事件: ondragenter - 当被鼠标拖动
import Vue from 'vue' import VueDragResize from 'vue-drag-resize' Vue . component ( 'vue-drag-resize' , VueDragResize ) Event  对象 Event  对象代表事件的状态,比如事件在其中发生的元素、键盘按键的状态、鼠标的位置、鼠标按钮的状态,事件通常与函数结合使用,函数不会在事件发生前被执行! Event  对象的产生当用户单击某个元素的时候,我们给这个元素注册的事件就会触发,该事件的本质就是一个函数,而该函数的形参接收一个event对象. onmousedow
有很多关于如何使事物在网页中可拖动的教程。 jQuery是最简单的方法之一。 您甚至不需要jQuery UI,只需鼠标方向功能的一点帮助,也许还有一些可选的处理即可。 但是,如果您不想触摸任何jQuery代码但仍希望使事物可拖动怎么办? 然后, draggabilly.js是适合您的工具。 使用Draggabilly.js ,您可以使网页上的任何元素都可拖动。 您可以自定义可拖动元素的行为...
QToolButton是Qt框架中提供的一个控件,它可以被用来创建一个按钮,同时也可以在按钮上添加图标或者文字。实现动态拖拽drag、drop功能,可以通过QToolButton的dragEnterEvent、dragMoveEvent、dragLeaveEvent、dragEnterEvent、dropEvent等事件来完成。 首先,需要在QToolButton中开启拖拽功能,可以通过setDragEnabled(true)方法来实现。在该方法开启后,只有在mousePressEvent事件中按下鼠标左键后进行拖动,才能触发drag事件。当鼠标拖动到对应的目标窗口时,需要在dragEnterEvent中处理一些事件以识别目标窗口是否可以接收该拖拽操作。 当判断目标窗口可以接收该拖拽操作后,需要在dragMoveEvent中实现一个视觉提示,表示该窗口可接收该拖拽操作。当鼠标松开时,将其实现放置在目标位置上(dropEvent事件中),并确保该操作已正确完成。此外,需要在dragLeaveEvent中释放拖拽操作所占用的资源。 总之,通过QToolButton的事件处理,可以实现一个定制的鼠标拖拽操作。实现这个拖拽操作对于提高应用程序的可用性和友好性将是非常有益的。
Error: Compiling RuleSet failed: A Rule must not have a ‘options‘ property when it has a ‘use‘ prope
nullpoint__: 你这也没分析为什么啊, ignore-scripts是忽略构建脚本, 但是不构建run build编译项目不行, 没办法处理scss文件, 所以还得加node rebuild node-sass 重新编译. 我不明白的是, 为什么npm i 阶段 node-sass就会报python2 的错误, npm rebuild node-sass就不需要. 而且我同事的电脑也没装python环境, npm i 的时候node-sass就不会报乱七八糟的. 百思不解, 坑的一批的node-sass.