最近写到一个需求是悬浮球拖动,看了很多网上的案例,要么移动端很流畅那么PC端就很卡,要么双端(ps:双端是指移动端和PC端)都很卡。于是自己就在网上百度改造了一款双端基本上很流畅的就能拖拽
这里面的 v-drag 主要是用于移动端
之后就要去注册一下事件(因为我是在html中引入的vue.js所以我的data中没有写return 如果大家是在vue项目的话记得请在return中写哦~~)
data: { boxnew: true, bindicon: true, //浮标拖动 clientWidth: 0, clientHeight: 0, timer: null, currentTop: 0, left: 90, top: 0, activeArr: "GiftBags", }, directives: { drag: { // 在要拖拽的元素上加 v-drag // 指令的定义 bind: function (el) { let odiv = el //获取当前元素 odiv.onmousedown = function (e) { //算出鼠标相对元素的位置 let startX = e.clientX; let startY = e.clientY; let starL = odiv.offsetLeft let starT = odiv.offsetTop let maxLeft = document.documentElement.offsetWidth - odiv.offsetWidth; starL = starL > maxLeft ? maxLeft : starL; document.onmousemove = function (e) { odiv.style.transition = 'none'; // 元素的位置 let left = e.clientX - startX + starL; let top = e.clientY - startY + starT; // 边界判断 let maxLeft = document.documentElement.offsetWidth; let minLeft = 0; left = left > maxLeft ? maxLeft : left; left = left < minLeft ? minLeft : left; //绑定元素位置到positionX和positionY上面 this.positionX = top this.positionY = left //移动当前元素 odiv.style.left = left + 'px' odiv.style.top = top + 'px' } document.onmouseup = () => { let boxLeft = parseInt(odiv.style.left), pageX = document.documentElement.offsetWidth - odiv.offsetWidth; document.onmousemove = null document.onmouseup = null // 悬浮左右滑动的逻辑 if (boxLeft < pageX / 2) { odiv.style.left = 0 + 'px'; odiv.style.transition = 'left .3s'; } else { odiv.style.left = pageX + 'px'; odiv.style.transition = 'left .3s'; } } } }, }, }, props: { itemWidth: { // 悬浮按钮宽度 type: Number, default: 50 }, itemHeight: { // 悬浮按钮高度 type: Number, default: 50 }, gapWidth: { // 距离左右两边距离 type: Number, default: -25 }, coefficientHeight: { // 从上到下距离比例 type: Number, default: 0.1 } },后面我们就需要去做一些拖拽的操作啦,这些操作可都得写在methods下面哦
onBtnClicked() { this.$emit("onFloatBtnClicked"); }, handleScrollStart() { this.timer && clearTimeout(this.timer); this.timer = setTimeout(() => { this.handleScrollEnd(); }, 300); this.currentTop = document.documentElement.scrollTop || document.body.scrollTop; if (this.left > this.clientWidth / 2) { this.left = this.clientWidth - this.itemWidth / 2; } else { this.left = -this.itemWidth / 2; } }, handleScrollEnd() { let scrollTop = document.documentElement.scrollTop || document.body.scrollTop; if (scrollTop === this.currentTop) { if (this.left > this.clientWidth / 2) { this.left = this.clientWidth - this.itemWidth - this.gapWidth; } else { this.left = this.gapWidth; } } },最后我在mounted里面做了一个判断是pc然后再确定悬浮球的边距
mounted() { // 判断Pc端 if (document.documentElement.clientWidth > 750) { this.$refs.floatButton.vue = this; // 将实例传递给当前元素 } //移动端拖拽 this.clientWidth = document.documentElement.clientWidth; this.clientHeight = document.documentElement.clientHeight; this.left = this.clientWidth - this.itemWidth - this.gapWidth; this.top = this.clientHeight * this.coefficientHeight; this.$nextTick(() => { const floatButton = this.$refs.floatButton; floatButton.addEventListener("touchstart", () => { floatButton.style.transition = "none"; }); // 在拖拽的过程中,组件应该跟随手指的移动而移动。 floatButton.addEventListener("touchmove", e => { console.log("移动中", e); if (e.targetTouches.length === 1) { // 一根手指 let touch = e.targetTouches[0]; this.left = touch.clientX - 40; this.top = touch.clientY - 25; } }); // 拖拽结束以后,重新调整组件的位置并重新设置过度动画。 floatButton.addEventListener("touchend", () => { floatButton.style.transition = "all 0.3s"; if (this.left > document.documentElement.clientWidth / 2) { this.left = document.documentElement.clientWidth - 20; } else { this.left = -20; } }); }); },到这,,,,悬浮球拖拽的操作就完成了,如果大家有需要的话完全拿代码去试一试哦,最后谢谢大家的采纳,如果有什么更好的方法欢迎联系,谢谢大家~~