浮动效果:图片依次为未触发,触发,拖拽
view模块
<template>
<div>
<div id="moveDiv" @mouseleave="yichu()" @mousedown="down()" @mousemove="move" @mouseup="end" @touchend="end" class="NMH-g-plugin NMH-g-navicon" :class='[jinruD==1?"Jnmh-open":""]'>
<button class="Jnmh-btnlogo" @mouseover="jinru()" ></button>
<ins class="Jnmh-btnlogohover"></ins>
<ul class="Jnmh-m-submenu">
<li class="Jnmh-subli" v-for="(item,index) in tabList" :key="index" :style="{transform: 'rotate('+item.jd+'deg)'}">
<dl class="Jnmh-subdl">
<dt class="NMH-subdt">{{item.name}}</dt>
<dd class="NMH-subdd"></dd>
</dl>
</li>
</ul>
</div>
</div>
</template>
js动态监听处理数据变化
<script>
export default {
data() {
return {
flags: false,
positionTemp: { x: 0, y: 0 }, // 记录手指点击的位置
nx: '',
ny: '',
dx: '',
dy: '',
xPum: '',
yPum: '',
tabList:[{name:"电商平台"},{name:"电商平台2"},{name:"电商平台2"},{name:"电商平台2"},{name:"电商平台3"},{name:"电商平台4"}],
jinruD:0
}
},
methods: {
jinru(){
this.jinruD=1
this.jiaodu()
},
yichu(){
this.jinruD=0
this.tabList.map((item)=>{
item.jd=0
})
},
jiaodu(){
var lilen = this.tabList.length;
var avgDeg = 180/(lilen-1);// 平均角度
var initDeg = 0;// 起始方向角度
let windowWidth = document.documentElement.clientWidth
var WidthR = windowWidth/2
if(this.xPum < WidthR){
// 如果悬浮球被拖拽到左边,则二级菜单则显示右侧
initDeg = 180;
}else{
// 默认悬浮球在右边,二级菜单显示在左侧
initDeg = 0;
}
for(var i=0,j=lilen-1; i<lilen; i++,j--) {
var d = initDeg - (i*avgDeg);
var z = initDeg?j:i;
this.tabList[i].jd = d
}
},
// 实现移动端拖拽
down(){
if (this.fixed) {
return
}
this.flags = true;
var touch;
// 该if判断是用touch还是mouse来移动
if (event.touches) {
touch = event.touches[0];
} else {
touch = event;
}
this.positionTemp.x = touch.clientX; // 手指点击后的位置
this.positionTemp.y = touch.clientY;
this.dx = moveDiv.offsetLeft; // 移动的div元素的位置
this.dy = moveDiv.offsetTop;
// console.log("moveDiv.offsetLeft", moveDiv.offsetLeft)
// console.log("touch.clientX", touch.clientX)
},
move(){
if(this.flags) {
var touch ;
if(event.touches){
touch = event.touches[0];
}else {
touch = event;
}
this.nx = touch.clientX - this.positionTemp.x; // 手指移动的变化量
this.ny = touch.clientY - this.positionTemp.y;
this.xPum = this.dx + this.nx; // 移动后,div元素的位置
this.yPum = this.dy + this.ny;
let windowWidth = document.documentElement.clientWidth
let windowHeight = document.documentElement.clientHeight
// console.log("window.clientWidth", windowWidth)
// console.log(this.xPum)
// console.log(" moveDiv.clientWidth", moveDiv.clientWidth)
if (this.xPum > 0 && (this.xPum + moveDiv.clientWidth < windowWidth)) {
// movediv的左右边,未出界
moveDiv.style.left = this.xPum + "px";
} else if (this.xPum <= 0) {
// 左边出界,则左边缘贴边
moveDiv.style.left = 0 + "px";
} else if (this.xPum + moveDiv.clientWidth >= windowWidth) {
// 右边缘出界
moveDiv.style.left = (windowWidth - moveDiv.clientWidth) + "px";
// console.log("dx", windowWidth - moveDiv.clientWidth)
}
// 上下未出界
if (this.yPum > 0 && (this.yPum + moveDiv.clientHeight < windowHeight)) {
moveDiv.style.top = this.yPum +"px";
} else if (this.yPum <= 0) {
// 上边缘出界
moveDiv.style.top = 0 + "px"
} else if (this.yPum + moveDiv.clientHeight >= windowHeight) {
// 下边缘
// console.log("windowHeight:", windowHeight)
moveDiv.style.top = windowHeight - moveDiv.clientHeight + "px"
}
this.jiaodu()
document.addEventListener("touchmove", this.preventDefault, { passive: false })
document.addEventListener("mousemove", this.preventDefault, { passive: false })
}
},
//鼠标释放时候的函数,鼠标释放,移除之前添加的侦听事件,将passive设置为true,不然背景会滑动不了
end(){
this.flags = false
// 注意事项,在添加和删除监听事件时,其function必须是同名的函数,不能为匿名函数。
document.removeEventListener('touchmove',this.preventDefault, false)
document.removeEventListener('mousemove',this.preventDefault, false)
// 下面两句是保证在移除监听事件后,除了悬浮球的部分还能够滑动,如果不添加,则无法滑动
document.addEventListener("touchmove", function(e) {
window.event.returnValue = true
})
document.addEventListener("mousemove", function(e) {
window.event.returnValue = true
})
},
preventDefault(e) {
e.preventDefault()
}
},
mounted() {
this.xPum = document.documentElement.clientWidth
}
}
</script>
css样式
<style scoped>
html,body{
width: 100%;
height: 100%;
margin: 0;padding: 0;
}
/*导航图标*/
.NMH-g-navicon{
position: fixed;
top: 40%;
right: 020px;
width: 100px;
height: 100px;
}
.NMH-g-navicon.Jnmh-onleft{
right: auto;
left: 020px;
}
/*导航图标logo按钮*/
.NMH-g-navicon .Jnmh-btnlogo{
position: absolute;
display: block;
width: 100px;
height: 100px;
top: 50%;
right: 0;
margin-top: -50px;
border: 0;
background: url(../assets/logo.png) no-repeat center center;
background-size: 95% 95%;
border: 1px solid rgba(0, 0, 0, 0.1);
box-shadow: rgba(0, 0, 0, 0.12) 0px 6px 10px 0px;
outline: none;
border-radius: 50%;
z-index: 1;
}
.NMH-g-navicon .Jnmh-btnlogohover{
position: absolute;
display: block;
width: 100px;
height: 100px;
top: 50%;
right: 0;
margin: 0;padding: 0;
margin-top: -50px;
border: 0;
overflow: hidden;
/*background-color: red;*/
}
/*导航图标logo按钮-鼠标经过*/
.NMH-g-navicon.Jnmh-open .Jnmh-btnlogohover{
margin-top: -150px;
width: 200px;
height: 300px;
border-radius: 150px 0 0 150px;
}
.NMH-g-navicon.Jnmh-onleft .Jnmh-btnlogohover{
left: 0;
right: auto;
border-radius: 0 150px 150px 0;
}
/*导航图标菜单子容器*/
.NMH-g-navicon .Jnmh-m-submenu{
position: absolute;
background-color: transparent;
list-style: none;
top: -020px;
bottom: -020px;
left: -020px;
right: -020px;
margin: 0;
padding: 0;
}
.NMH-g-navicon .Jnmh-m-submenu .Jnmh-subli{
position: absolute;
width: 100%;height: 100%;
transform: rotate(0deg);
-webkit-transform: rotate(0deg);
transition: all 0.8s ease-in-out;
}
.Jnmh-m-submenu .Jnmh-subdl{
position: absolute;
left: 50%;
bottom: 100%;
width: 0;
height: 0;
line-height: 1px;
margin-left: 0;
background: #fff;
border-radius: 50%;
text-align: center;
font-size: 1px;
overflow: hidden;
cursor: pointer;
box-shadow: none;
transition: all 0.8s ease-in-out, color 0.1s, background 0.1s;
}
/*导航图标-展开菜单时*/
.NMH-g-navicon.Jnmh-open .Jnmh-m-submenu .Jnmh-subdl{
width: 80px;
height: 80px;
line-height: 80px;
margin-left: -40px;
box-shadow: 0 3px 3px rgba(0, 0, 0, 0.1);
font-size: 14px;
}
/*导航图标-三级菜单容器*/
.NMH-g-navicon.Jnmh-open .Jnmh-m-submenu .Jnmh-subdd{
position: absolute;
line-height: normal;
}