需求:
1. 每个页面都能自动加上悬浮按钮
2. 可拖拽
3. 点击返回首页
效果图:
方式一:js原生写法:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
let div = document.createElement('div');
let clientWidth = document.documentElement.clientWidth // 获取手机的像素宽度
let clientHeight = document.documentElement.clientHeight// 获取手机的像素高度
div.style.boxShadow = '0px 0px 0px 0.5em #e0e1e9' ;
div.style.width = "24px";
div.style.height = "24px";
div.style.left = clientWidth - 50+'px';
console.log("初始位置left"+div.style.left)
div.style.top = clientHeight * 0.6+'px';
div.style.zIndex = '100000';
div.style.position= 'fixed';
div.style.background = 'red';
div.style.transition='all 0.3s';
div.style.bottom='436px';
div.style.right= 0;
div.style.margin='5px 10px';
div.style.background='rgb(197 203 211)'
div.style.borderRadius = '15px';
document.body.appendChild(div);
var divattr = document.createAttribute("id");
divattr.value = "float_info";
//把属性id = "float_info"添加到div
div.setAttributeNode(divattr);
let flag = 0; //标记是拖曳还是点击
var oDiv = document.getElementById('float_info');
oDiv.style.display = 'block'; // 显示元素
oDiv.addEventListener("touchstart", () => {
flag = 0;
oDiv.style.transition = 'none'
})
// 在拖拽的过程中,按钮应该跟随鼠标的移动而移动。
oDiv.addEventListener("touchmove", (e) => {
flag=1
console.log('移动中', e)
if (e.targetTouches.length === 1) { // 一根手指
e.preventDefault();// 阻止默认的滚动行为
div.style.left = e.targetTouches[0].clientX-20 +'px'//clientX:触摸目标在视口中的x坐标。
div.style.top = e.targetTouches[0].clientY -25 +'px'//clientY:触摸目标在视口中的y坐标。
console.log('移动中', div.style.left)
}
})
// 拖拽结束以后,重新调整按钮的位置并重新设置过度动画。
oDiv.addEventListener("touchend", () => {
// 如果是点击跳转到首页
if(flag==0){
that.$router.push({
path: "/workspaces/views/index/index",
});
}else {
div.style.transition = 'all 0.3s'
console.log('拖拽结束后left', div.style.left)
console.log('拖拽结束后top', div.style.top)
if ( parseInt(div.style.left)> (document.documentElement.clientWidth / 2)) {
div.style.left = document.documentElement.clientWidth -50+'px';
} else {
div.style.left = 0+'px'
}
// 控制其超出屏幕回到原始位置
if ( parseInt(div.style.top)> (document.documentElement.clientHeight)|| parseInt(div.style.top)<0) {
div.style.top = document.documentElement.clientHeight* 0.6+'px'
}
}
})
</script>
</body>
</html>
注:如果想在vue项目中的每个页面都加上悬浮按钮,可用js,写在APP.vue的onLaunch()函数里
方式二:
1.创建一个FloatingButton.vue的组件
<template>
<!-- 子组件 -->
<div class="float_button">
<div
@click="onBtnClicked"
ref="floatButton"
class="float_info"
:style="{'width': itemWidth + 'px','margin':'5px 10px', 'height': itemHeight + 'px', 'left': left + 'px', 'top': top + 'px'}"
>
<span class="text">返回首页</span>
</div>
</div>
</template>
<script>
export default {
data() {
return {
clientWidth: 0,
clientHeight: 0,
timer: null,
currentTop: 0,
left: 0,
top: 0,
itemWidth: 70 , //按钮宽度
isShort: true,
itemHeight: 32, // 悬浮按钮高度
gapWidth: 0, // 距离左右两边距离
coefficientHeight: 0.6, // 从上到下距离比例
}
},
props: {
},
computed: {
},
created() {
// console.log('屏幕宽度', document.documentElement.clientWidth)
// console.log('屏幕高度度', document.documentElement.clientHeight)
let type = navigator.userAgent;
// console.log('设备', type)
this.clientWidth = document.documentElement.clientWidth
this.clientHeight = document.documentElement.clientHeight
this.left = this.clientWidth - this.itemWidth - this.gapWidth - 20;
this.top = this.clientHeight * this.coefficientHeight
},
watch: {
left(n, o) {
}
},
methods: {
onBtnClicked() {
},
handleScrollStart() {
console.log('这是啥时候触发呀?ScrollStart')
this.timer && clearTimeout(this.timer)
this.timer = setTimeout(() => {
this.handleScrollEnd()
}, 300)
this.currentTop = document.documentElement.scrollTop || document.body.scrollTop
if (this.left > this.clientWidth / 2) {
this.left = this.clientWidth - this.itemWidth / 2
} else {
this.left = -this.itemWidth / 2
}
},
handleScrollEnd() {
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
if (scrollTop === this.currentTop) {
if (this.left > this.clientWidth / 2) {
this.left = this.clientWidth - this.itemWidth - this.gapWidth
} else {
this.left = this.gapWidth
}
clearTimeout(this.timer)
}
},
},
mounted() {
this.$nextTick(() => {
const floatButton = this.$refs.floatButton
floatButton.addEventListener("touchstart", () => {
floatButton.style.transition = 'none'
})
// 在拖拽的过程中,组件应该跟随手指的移动而移动。
floatButton.addEventListener("touchmove", (e) => {
// console.log('移动中', e)
if (e.targetTouches.length === 1) { // 一根手指
document.body.addEventListener('touchmove', this.bodyScroll, { passive: false }); //禁止页面滑动
let touch = e.targetTouches[0]
this.left = touch.clientX - 20
this.top = touch.clientY - 25
}
})
// 拖拽结束以后,重新调整组件的位置并重新设置过度动画。
floatButton.addEventListener("touchend", () => {
floatButton.style.transition = 'all 0.3s'
console.log('拖拽结束后left', this.left)
document.body.removeEventListener('touchmove', this.bodyScroll, { passive: false }); //解除页面禁止滑动
if (this.left > document.documentElement.clientWidth / 2) {
this.left = document.documentElement.clientWidth - this.itemWidth - 20;
} else {
this.left = 0
}
})
})
},
beforeDestroy() {
// 添加监听页面滚动
window.removeEventListener('scroll', this.handleScrollStart)
},
destroyed() { }
}
</script>
<style lang="scss" scoped>
.float_button {
.float_info {
box-shadow: #1666ca;
transition: all 0.3s;
position: fixed;
bottom: 436px;
right: 0;
margin: 5px 10px;
display: flex;
flex-flow: row;
justify-content: center;
align-items: center;
z-index: 999;
background: #1666ca;
background-color: rgba(22, 102, 202, 0.6);
border-radius: 10px;
cursor: pointer;
.text {
font-size: 12px;
color: #fff;
}
}
}
</style>
2.然后在main.js中注册全局组件(这里大家根据自己的实际路径替换)
import FloatingButton from '@/workspaces/tools/FloatingButton.vue';
Vue.component('FloatingButton', FloatingButton)
3.最后在需要这个悬浮按钮的页面模板中用这个组件就可以了
<FloatingButton/>