按钮可以替换为图片/动图,根据需求选择
<template>
<div class="float_button">
<div
@click="onBtnClicked"
ref="floatButton"
class="float_info"
:style="{
width: itemWidth + 'px',
height: itemHeight + 'px',
left: left + 'px',
top: top + 'px',
bottom: bottom + 'px'
}"
>
<div>按钮</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
clientWidth: 0,
clientHeight: 0,
timer: null,
currentTop: 0,
left: 0,
top: 0,
bottom: 0
};
},
props: {
text: {
// 按钮文本内容
type: String,
default: ""
},
itemWidth: {
// 悬浮按钮宽度
type: Number,
default: 55
},
itemHeight: {
// 悬浮按钮高度
type: Number,
default: 55
},
gapWidth: {
// 距离左右两边距离
type: Number,
default: 10
},
coefficientHeight: {
// 从上到下距离比例
type: Number,
default: 0.55
}
},
created() {
this.clientWidth = document.documentElement.clientWidth;
this.clientHeight = document.documentElement.clientHeight;
this.left = this.clientWidth - this.itemWidth - this.gapWidth;
this.top = this.clientHeight * this.coefficientHeight;
this.bottom = this.clientHeight * this.coefficientHeight;
},
methods: {
onBtnClicked() {
this.$emit("onFloatBtnClicked");
},
handleScrollStart() {
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 => {
if (e.targetTouches.length === 1) {
// 一根手指
let touch = e.targetTouches[0];
this.left = touch.clientX - 20;
this.top = touch.clientY - 25;
this.bottom = touch.clientY;
}
});
// 拖拽结束以后,重新调整组件的位置并重新设置过度动画。
floatButton.addEventListener("touchend", () => {
floatButton.style.transition = "all 0.3s";
if (this.left > document.documentElement.clientWidth / 2) {
this.left = document.documentElement.clientWidth - 65;
} else {
this.left = 10;
}
if (this.top < document.documentElement.clientTop / 2) {
this.top = this.clientHeight * this.coefficientHeight;
}
if (this.bottom >= document.documentElement.clientHeight) {
this.top = this.clientHeight * this.coefficientHeight;
}
});
});
},
beforeDestroy() {
// 添加监听页面滚动
window.removeEventListener("scroll", this.handleScrollStart);
}
};
</script>
<style lang="scss">
@-webkit-keyframes welfare {
10% {
transform: rotate(15deg);
}
20% {
transform: rotate(-10deg);
}
30% {
transform: rotate(5deg);
}
40% {
transform: rotate(-5deg);
}
50% {
transform: rotate(5deg);
}
100% {
transform: rotate(-5deg);
}
}
.float_button {
.float_info {
transition: all 0.3s;
position: fixed;
//bottom: 436px;
right: 0;
display: flex;
flex-flow: column;
justify-content: center;
align-items: center;
z-index: 100;
cursor: pointer;
-webkit-animation: welfare 3s linear infinite;
}
}
</style>