完整的代码, 可以复制引用
Vue 右上角拖拽的客服图标组件
<template>
<!-- 客服图标链接 -->
<a :href="$store.state.user.info.kefulink" class="server"
ref="drawable"
:style="{right: right, top: top}"
@touchstart="touchstart"
@touchend="touchend"
@touchmove="mousemove"
>
<!-- 客服图标 -->
<img src="../assets/img/kefu.png" class="server-icon">
</a>
</template>
<script>
export default {
props: {
top: 0,
right: 0,
isOnlyLeft: Boolean, // 仅在左边拖动时使用
isOnlyRight: Boolean, // 仅在右边拖动时使用
},
data() {
return {
flag: false // 标志位,用于判断是否正在进行拖动操作
};
},
methods: {
touchstart() {
this.flag = true;
document.getElementById('app').style = 'overflow: hidden;'; // 禁用页面滚动条
this.$refs.drawable.style.transition = 'none'; // 取消动画,使拖拽更加流畅
},
touchend() {
this.flag = false;
this.$refs.drawable.style.transition = 'all 0.2s'; // 恢复动画
document.getElementById('app').style = 'overflow: auto;'; // 恢复页面滚动
let left = this.$refs.drawable.offsetLeft;
let screenWidth = window.screen.width;
let oWidth = this.$refs.drawable.offsetWidth;
if (left + oWidth / 2 <= screenWidth / 2) {
this.$refs.drawable.style.left = '0px';
} else {
this.$refs.drawable.style.left = screenWidth - oWidth + 'px';
}
},
mousemove(e) {
e.preventDefault(); // 阻止默认行为,避免和其他事件冲突
if (this.flag) {
let clientY = e.targetTouches[0].clientY; // 获取当前触摸点的位置
let clientX = e.targetTouches[0].clientX;
let offsetHeight = this.$refs.drawable.offsetHeight;
let offsetWidth = this.$refs.drawable.offsetWidth;
let top = clientY - offsetHeight / 2; // 计算元素应该移动到的位置
let left = clientX - offsetWidth / 2;
let screenWidth = window.screen.width;
let screenHeight = window.screen.height;
let maxTop = screenHeight - offsetHeight;
let maxLeft = screenWidth - offsetWidth;
if (top <= 0) top = 0;
if (top > maxTop) top = maxTop;
if (left <= 0) left = 0;
if (left > maxLeft) left = maxLeft;
this.$refs.drawable.style.top = top + 'px'; // 更新元素的位置
this.$refs.drawable.style.left = left + 'px';
}
}
},
}
</script>
<style lang="scss">
.server {
position: fixed; // 固定定位
z-index: 100; // z轴层级
top: 75px;
right: 0px;
width: 48px;
border-radius: 50%; // 圆形边框
}
</style>