項目需求
實現一個懸浮按鈕,可在每個頁面懸浮,為了不遮擋可以再瀏覽器可視區(qū)任意移動,并且不能移動出可是區(qū)域
實現方式
通過vue自定義指令,監(jiān)聽鼠標移動事件,計算位移,使元素移動,
效果:
可移動的懸浮按鈕
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:鼠標距離瀏覽器有效區(qū)域邊緣的橫向距離
// clientY:鼠標距離瀏覽器有效區(qū)域邊緣的縱向距離
// 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
// 限制懸浮按鈕不能出瀏覽器可視區(qū)
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 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>
待優(yōu)化點:只能按空白位置移動 按著icon圖片的話,圖片會先移動出去
=============================分割線=======================================
bug:
1.點擊圖標移動popover會彈出來
解決辦法:鼠標移動時popover設置為dispaly:none
2.點擊手冊移動,移動完a鏈接會跳轉
解決辦法:定義一個點擊變量isClick 如果移動了 就阻止a鏈接跳轉 retur false 可以阻止a鏈接跳轉
3.鼠標松開,元素仍可以拖動onmouseup不起作用
原因:觸發(fā)了H5原生的拖拽事件,以至于不會監(jiān)聽到onmouseup
解決辦法:在拖拽事件里面調用ev.preventDefault()文章來源:http://www.zghlxwxcb.cn/news/detail-499563.html
修改后代碼:
文章來源地址http://www.zghlxwxcb.cn/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模板網以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網!