Skip to content

Commit a7194bb

Browse files
committed
add: Vue 浮动按钮组件
1 parent 98b65f7 commit a7194bb

File tree

1 file changed

+141
-0
lines changed

1 file changed

+141
-0
lines changed

admin/src/views/home/float.vue

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<template>
2+
<div
3+
class="ys-float-btn"
4+
:style="{'width':itemWidth+'px','height':itemHeight+'px','left':left+'px','top':top+'px'}"
5+
ref="div"
6+
@click="onBtnClicked"
7+
>
8+
<slot name="icon"></slot>
9+
<p>{{text}}</p>
10+
</div>
11+
</template>
12+
13+
<script>
14+
export default {
15+
name: 'FloatImgBtn',
16+
props: {
17+
text: {
18+
type: String,
19+
default: '默认文字'
20+
},
21+
itemWidth: {
22+
type: Number,
23+
default: 60
24+
},
25+
itemHeight: {
26+
type: Number,
27+
default: 60
28+
},
29+
gapWidth: {
30+
type: Number,
31+
default: 10
32+
},
33+
coefficientHeight: {
34+
type: Number,
35+
default: 0.8
36+
}
37+
},
38+
created() {
39+
this.clientWidth = document.documentElement.clientWidth
40+
this.clientHeight = document.documentElement.clientHeight
41+
this.left = this.clientWidth - this.itemWidth - this.gapWidth
42+
this.top = this.clientHeight * this.coefficientHeight
43+
},
44+
mounted() {
45+
window.addEventListener('scroll', this.handleScrollStart)
46+
this.$nextTick(() => {
47+
const div = this.$refs.div
48+
div.addEventListener('touchstart', () => {
49+
div.style.transition = 'none'
50+
})
51+
div.addEventListener('touchmove', (e) => {
52+
if (e.targetTouches.length === 1) {
53+
let touch = event.targetTouches[0]
54+
this.left = touch.clientX - this.itemWidth / 2
55+
this.top = touch.clientY - this.itemHeight / 2
56+
}
57+
})
58+
div.addEventListener('touchend', () => {
59+
div.style.transition = 'all 0.3s'
60+
if (this.left > this.clientWidth / 2) {
61+
this.left = this.clientWidth - this.itemWidth - this.gapWidth
62+
} else {
63+
this.left = this.gapWidth
64+
}
65+
})
66+
67+
})
68+
},
69+
beforeDestroy() {
70+
window.removeEventListener('scroll', this.handleScrollStart)
71+
},
72+
methods: {
73+
onBtnClicked() {
74+
this.$emit('onFloatBtnClicked')
75+
},
76+
handleScrollStart() {
77+
this.timer && clearTimeout(this.timer)
78+
this.timer = setTimeout(() => {
79+
this.handleScrollEnd()
80+
}, 300)
81+
this.currentTop = document.documentElement.scrollTop || document.body.scrollTop
82+
if (this.left > this.clientWidth / 2) {
83+
this.left = this.clientWidth - this.itemWidth / 2
84+
} else {
85+
this.left = -this.itemWidth / 2
86+
}
87+
},
88+
handleScrollEnd() {
89+
let scrollTop = document.documentElement.scrollTop || document.body.scrollTop
90+
if (scrollTop === this.currentTop) {
91+
if (this.left > this.clientWidth / 2) {
92+
this.left = this.clientWidth - this.itemWidth - this.gapWidth
93+
} else {
94+
this.left = this.gapWidth
95+
}
96+
clearTimeout(this.timer)
97+
}
98+
}
99+
},
100+
data() {
101+
return {
102+
timer: null,
103+
currentTop: 0,
104+
clientWidth: 0,
105+
clientHeight: 0,
106+
left: 0,
107+
top: 0
108+
}
109+
}
110+
}
111+
</script>
112+
113+
<style scoped>
114+
.ys-float-btn {
115+
background: rgb(255, 255, 255);
116+
box-shadow: 0 2px 10px 0 rgba(0, 0, 0, 0.1);
117+
border-radius: 50%;
118+
color: #666666;
119+
z-index: 20;
120+
transition: all 0.3s;
121+
122+
display: flex;
123+
flex-direction: column;
124+
justify-content: center;
125+
align-items: center;
126+
127+
position: fixed;
128+
bottom: 20vw;
129+
}
130+
131+
.ys-float-btn img {
132+
width: 50%;
133+
height: 50%;
134+
object-fit: contain;
135+
margin-bottom: 3px;
136+
}
137+
138+
.ys-float-btn p {
139+
font-size: 7px;
140+
}
141+
</style>

0 commit comments

Comments
 (0)