概述
最近开发的项目中有一个分享的悬浮按钮,这个按钮遮挡了页面信息,产品经理跑过来问我,是否可以把这个按钮做成可以拖拽的,研究了一下轻松实现了这个功能,这里分享给大家。这个项目是基于vue的公众号网页,所以是通过vue来实现的,给大家一个参考。先来看一看效果:

分析
「1. 技术点」
- 插槽
- 固定定位
- 组件封装
- touchemove & mousemove 事件

「2. 实现思路」
- 首先封装drag-view组件,组件本身只处理拖拽逻辑,组件内容通过插槽由父组件传入。
- 将drag-view设置为固定定位,然后在move事件中计算出
left和top赋值给drag-view即可。
「3. 处理计算」
top 和 left 值的计算比较简单,我们只需要获取到触摸点的x、y坐标减去容器宽度、高度的一半即可,所以得出以下公式:
top = clientY - elHeight / 2;
left = clientX - elWidth / 2;
代码实现
「1. 组件部分」
<template>
<div
class="drag__wrapper"
ref="dragRef"
:style="{top:pos.y+'px', left:pos.x+'px'}"
@mousemove="onTouchMove"
@touchmove.stop="onTouchMove"
>
<slot />
</div>
</template>
<script>
export default {
props: {
position: {
type: Object,
default: () => ({
x: 300,
y: 500,
}),
},
},
data() {
return {
flags: false,
pos: {
x: 0,
y: 0,
},
};
},
mounted() {
// 设置默认值
this.pos = { ...this.$props.position };
// 获取容器元素的尺寸信息
const rect = this.$refs.dragRef.getBoundingClientRect();
// 获取容器元素尺寸的一半便于后面计算使用
this.wrapperHalfWidth = rect.width / 2;
this.wrapperHalfHeight = rect.height / 2;
// 获取屏幕的尺寸信息
const clientWidth =
document.body.clientWidth || document.documentElement.clientWidth;
const clientHeight =
document.body.clientHeight || document.documentElement.clientHeight;
// 获取拖拽元素在屏幕内可拖拽的边界值
this.maxX = clientWidth - rect.width;
this.maxY = clientHeight - rect.height;
},
methods: {
onTouchMove(event) {
// 获取触点,兼容PC和移动端
let touch;
if (event.touches) {
touch = event.touches[0];
} else {
touch = event;
}
// 定位滑块的位置
this.pos.x = touch.clientX - this.wrapperHalfWidth;
this.pos.y = touch.clientY - this.wrapperHalfHeight;
// 处理边界
if (this.pos.x < 0) {
this.pos.x = 0;
} else if (this.pos.x > this.maxX) {
this.pos.x = this.maxX;
}
if (this.pos.y < 0) {
this.pos.y = 0;
} else if (this.pos.y > this.maxY) {
this.pos.y = this.maxY;
}
// 阻止页面的滑动默认事件
event.preventDefault();
},
},
};
</script>
<style>
.drag__wrapper {
position: fixed;
}
</style>
「2. 调用」
<template>
<div class="page test bg-light">
<p class="tips">{{tips}}</p>
<drag-view :position="{x: 300, y : 500}">
<div class="box" @click="onTap">客服</div>
</drag-view>
</div>
</template>
<script>
import DragView from "../../components/DragView/DragView.vue";
export default {
data() {
return {
tips: "",
};
},
methods: {
onTap() {
this.tips = "点击客服按钮";
},
},
components: {
DragView,
},
};
</script>
<style scoped="scoped" lang="less">
.tips {
text-align: center;
margin: 50px 0;
color: cornflowerblue;
font-size: 22px;
}
.box {
width: 50px;
height: 50px;
background: cornflowerblue;
border-radius: 50%;
text-align: center;
line-height: 50px;
color: #ffffff;
font-size: 16px;
}
</style>
提示:
- 调用drag-view组件时通过position属性来设置拖拽按钮的初始位置。
- 拖拽按钮点击事件直接在父组件定义即可。
结尾
好了,各位小伙伴,今天的分享就到这里啦,喜欢我文章朋友可以点一波关注,谢谢啦。你的关注,是我继续努力下去的动力。
关注公众号,了解更多干货