likes
comments
collection
share

元素拖拽?一个vue指令搞定

作者站长头像
站长
· 阅读数 12

说在前面

🎈元素拖拽功能大家应该都不陌生了吧,今天我们一起来看看怎么编写一个vue指令来实现元素拖拽功能吧!

效果展示

元素拖拽?一个vue指令搞定

体验地址

jyeontu.xyz/jvuewheel/#…

实现思路

1、初始化

let startX,
    startY,
    currentX = 0,
    currentY = 0;
el.style.position = "relative";
el.parentNode.style.position = "relative";
el.style.cursor = "pointer";
  • (1)指令钩子函数 inserted:当被绑定的元素被插入到 DOM 中时,该函数被调用。
  • (2)初始化变量:
    • startX 和 startY 用于存储鼠标按下或触摸开始时的相对位置。
    • currentX 和 currentY 用于存储元素当前的偏移量。
  • (3)设置元素样式:
    • el.style.position = "relative":确保元素是相对定位的,这样移动时不会影响其他元素的布局。
    • el.parentNode.style.position = "relative":将父元素也设置为相对定位,这是为了确保子元素的定位是相对于父元素的。
    • el.style.cursor = "pointer":改变鼠标光标的样式,提供视觉反馈,表明元素可以被点击和拖动。

2、添加事件监听器

  • 对于鼠标操作,添加 mousedown 和 mouseup 事件监听器。
  • 对于触摸操作,添加 touchstart 和 touchend 事件监听器。
el.addEventListener("mousedown", function (event) {
    event.preventDefault();
    startX = event.pageX - currentX;
    startY = event.pageY - currentY;
    document.addEventListener("mousemove", onMouseMove);
    document.addEventListener("mouseup", onMouseUp);
});
el.addEventListener("touchstart", function (event) {
    event.preventDefault();
    startX = event.touches[0].clientX - currentX;
    startY = event.touches[0].clientY - currentY;
    document.addEventListener("touchmove", onTouchMove);
    document.addEventListener("touchend", onTouchEnd);
});
function onMouseUp() {
    document.removeEventListener("mousemove", onMouseMove);
    document.removeEventListener("mouseup", onMouseUp);
}
function onTouchEnd() {
    document.removeEventListener("touchmove", onTouchMove);
    document.removeEventListener("touchend", onTouchEnd);
}

3、事件处理函数:

  • onMouseMove 和 onTouchMove:在鼠标移动或触摸移动时调用,用于更新元素的位置。
  • onMouseUp 和 onTouchEnd:在鼠标松开或触摸结束时调用,用于移除 mousemove 和 touchmove 事件监听器,结束拖拽操作。
  • 拖拽函数 drag:更新元素的 top 和 left 样式,使元素移动到 currentX 和 currentY 指定的位置。
function onTouchMove(event) {
    event.preventDefault();
    currentX = event.touches[0].clientX - startX;
    currentY = event.touches[0].clientY - startY;
    drag(el);
}
function onMouseMove(event) {
    event.preventDefault();
    currentX = event.pageX - startX;
    currentY = event.pageY - startY;
    drag(el);
}
function drag(el) {
    el.style.top = currentY + "px";
    el.style.left = currentX + "px";
}

完整代码

export default {
    inserted: function (el) {
        let startX,
            startY,
            currentX = 0,
            currentY = 0;
        el.style.position = "relative";
        el.parentNode.style.position = "relative";
        el.style.cursor = "pointer";
        el.addEventListener("mousedown", function (event) {
            event.preventDefault();
            startX = event.pageX - currentX;
            startY = event.pageY - currentY;
            document.addEventListener("mousemove", onMouseMove);
            document.addEventListener("mouseup", onMouseUp);
        });
        el.addEventListener("touchstart", function (event) {
            event.preventDefault();
            startX = event.touches[0].clientX - currentX;
            startY = event.touches[0].clientY - currentY;
            document.addEventListener("touchmove", onTouchMove);
            document.addEventListener("touchend", onTouchEnd);
        });
        function onMouseMove(event) {
            event.preventDefault();
            currentX = event.pageX - startX;
            currentY = event.pageY - startY;
            drag(el);
        }
        function onMouseUp() {
            document.removeEventListener("mousemove", onMouseMove);
            document.removeEventListener("mouseup", onMouseUp);
        }
        function onTouchMove(event) {
            event.preventDefault();
            currentX = event.touches[0].clientX - startX;
            currentY = event.touches[0].clientY - startY;
            drag(el);
        }
        function onTouchEnd() {
            document.removeEventListener("touchmove", onTouchMove);
            document.removeEventListener("touchend", onTouchEnd);
        }
        function drag(el) {
            el.style.top = currentY + "px";
            el.style.left = currentX + "px";
        }
    },
};

组件库

组件文档

目前该组件也已经收录到我的组件库,组件文档地址如下: jyeontu.xyz/jvuewheel/#…

组件内容

组件库中还有许多好玩有趣的组件,如:

  • 悬浮按钮
  • 评论组件
  • 词云
  • 瀑布流照片容器
  • 视频动态封面
  • 3D轮播图
  • web桌宠
  • 贡献度面板
  • 拖拽上传
  • 自动补全输入框
  • 图片滑块验证

等等……

组件库源码

组件库已开源到gitee,有兴趣的也可以到这里看看:gitee.com/zheng_yongt…

觉得有帮助的可以点个star~

有什么问题或错误可以指出,欢迎pr~

有什么想要实现的组件或想法可以联系我~

公众号

关注公众号『前端也能这么有趣』,获取更多有趣内容。

发送『组件库』获取源码

说在后面

🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『前端也能这么有趣』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。

转载自:https://juejin.cn/post/7352079398072041535
评论
请登录