项目需求
实现一个悬浮按钮,可在每个页面悬浮,为了不遮挡可以再浏览器可视区任意移动,并且不能移动出可是区域
实现方式
通过vue自定义指令,监听鼠标移动事件,计算位移,使元素移动,
效果:
可移动的悬浮按钮
1.实现代码
<script>
export default {
name: 'FloatButton',
mounted () {
// 给floatButton的悬浮位置赋值初始值
const el = document.getElementsByClassName('float-button')[0]
let left = document.body.clientWidth - 58
el.style.left = left + 'px'
el.style.top = '300px'
window.addEventListener('resize', () => {
left = document.body.clientWidth - 58
el.style.left = left + 'px'
})
},
directives: {
move (el) {
console.log('move', el)
el.onmousedown = function (e) {
//获取鼠标点击处分别与div左边和div上边的距离:鼠标位置-div位置
// clientX:鼠标距离浏览器有效区域边缘的横向距离
// clientY:鼠标距离浏览器有效区域边缘的纵向距离
// offsetLeft是元素左边框外侧到body左边框的距离
// offsetTop是元素上边框外侧到body上框内侧的距离
// 如果元素有position就是和父级元素的距离
let startX = e.clientX - el.offsetLeft
let startY = e.clientY - el.offsetTop
// startX,startY鼠标与盒子边缘的距离
document.onmousemove = function (ev) {
let event = ev || window.event;
let moveX = event.clientX - startX
let moveY = event.clientY - startY
// 限制悬浮按钮不能出浏览器可视区
const maxWidth = document.body.clientWidth - 68
const minHeight = document.body.clientHeight - 151
if (moveX >= maxWidth) {
moveX = maxWidth
}
if (moveY >= minHeight) {
moveY = minHeight
}
if (moveX < 0) {
moveX = 0
}
if (moveY < 0) {
moveY = 0
}
// moveX元素左边缘距离浏览器左边缘的纵向距离
// moveY元素上边缘距离浏览器上边缘的纵向距离
el.style.left = moveX + "px"
el.style.top = moveY + "px"
// 赋值给样式
}
// 鼠标弹起时不再移动
document.onmouseup = function () {
document.onmousemove = null;
};
};
},
},
}
</script>
2.悬浮按钮组件
<template>
<div class="float-button" v-move>
<div class="headset box-item">
<el-popover
placement="left"
trigger="hover"
width="300"
popper-class="headset-popper"
>
<div class="content">
<div class="item">
<img src="../../assets/img/login/qqGroup.png" alt="" />
<div class="text">
<span class="desc">商家QQ交流群</span>
<span>群号:726103120</span>
<span>QQ扫码</span>
</div>
</div>
<div class="item">
<img src="../../assets/img/login/webchat.png" alt="" />
<div class="text">
<span class="desc">商家微信交流群</span>
<span>微信扫码</span>
</div>
</div>
</div>
<span slot="reference">
<img src="../../assets/img/service.png" alt="" />
</span>
</el-popover>
</div>
<div class="line"></div>
<div class="help box-item">
<el-tooltip placement="bottom">
<template #content>
<a href="https://j1wz15.axshare.com" target="_blank">操作手册</a>
</template>
<img src="../../assets/img/doc.png" alt="" />
</el-tooltip>
</div>
</div>
</template>
3.悬浮按钮样式
<style lang="scss" scoped>
.float-button {
position: fixed;
padding: 10px;
background: #ffffff;
box-shadow: rgb(100 100 111 / 20%) 0px 7px 29px 0px;
z-index: 999;
.box-item {
padding: 2px 4px;
cursor: pointer;
img {
width: 30px;
height: 30px;
}
}
.headset {
border-radius: 10px;
background: #3777f4;
}
.line {
margin: 8px 0;
border-bottom: 2px solid #d7d7d7;
}
}
.headset-popper {
.content {
padding: 0 10px;
.item {
display: flex;
padding: 10px 0;
&:first-child {
border-bottom: 1px solid #f8f8f8;
}
img {
padding: 2px;
margin-right: 20px;
width: 120px;
height: 120px;
border: 2px solid #e0ebfb;
}
.text {
display: flex;
font-size: 12px;
flex-direction: column;
justify-content: start;
align-content: center;
line-height: 24px;
.desc {
font-size: 16px;
color: #328afc;
}
}
}
}
}
</style>
待优化点:只能按空白位置移动 按着icon图片的话,图片会先移动出去
=============================分割线=======================================
bug:
1.点击图标移动popover会弹出来
解决办法:鼠标移动时popover设置为dispaly:none
2.点击手册移动,移动完a链接会跳转
解决办法:定义一个点击变量isClick 如果移动了 就阻止a链接跳转 retur false 可以阻止a链接跳转
3.鼠标松开,元素仍可以拖动onmouseup不起作用
原因:触发了H5原生的拖拽事件,以至于不会监听到onmouseup
解决办法:在拖拽事件里面调用ev.preventDefault()文章来源:https://www.toymoban.com/news/detail-499563.html
修改后代码:
文章来源地址https://www.toymoban.com/news/detail-499563.html
directives: {
move (el) {
let isClick = true
el.onmousedown = function (e) {
const popoverEle = document.getElementsByClassName('el-popover')[0]
isClick = true
//获取鼠标点击处分别与div左边和div上边的距离:鼠标位置-div位置
let startX = e.clientX - el.offsetLeft
let startY = e.clientY - el.offsetTop
if (e.stopPropagation) e.stopPropagation();
if (e.preventDefault) e.preventDefault();
document.onmousemove = function (ev) {
isClick = false
popoverEle.style.display = 'none'
let event = ev || window.event;
let moveX = event.clientX - startX
let moveY = event.clientY - startY
const maxWidth = document.body.clientWidth - 68
const minHeight = document.body.clientHeight - 151
if (moveX >= maxWidth) {
moveX = maxWidth
}
if (moveY >= minHeight) {
moveY = minHeight
}
if (moveX < 0) {
moveX = 0
}
if (moveY < 0) {
moveY = 0
}
el.style.left = moveX + "px"
el.style.top = moveY + "px"
}
document.onclick = function () {
return isClick
};
document.onmouseup = function () {
document.onmousemove = null;
};
// 解决有些时候,在鼠标松开的时候,元素仍然可以拖动;
document.ondragstart = function (ev) {
ev.preventDefault();
};
document.ondragend = function (ev) {
ev.preventDefault();
};
};
},
},
}
到了这里,关于vue自定义指令directives+div跟随鼠标移动的floatButton组件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!