直接上代码先 。组件 。次组件功能没有全部完善,需要自己改动 float.vue
<template>
<div class="ys-float-btn" :style="{'width':itemWidth+'px','height':itemHeight+'px','left':left+'px','top':top+'px'}"
ref="div"
@touchstart.stop="gtouchstart()"
@touchmove.stop="gtouchmove()"
@touchend.stop="gtouchend()"
@click.stop ="onBtnClicked">
<slot></slot>
<!-- <p>{{text}}</p> -->
</div>
</template>
<script>
export default {
name: "FloatImgBtn",
props:{
// 背景页面需要设置宽度。或者滑动不会顺畅
itemWidth:{
type:Number,
default:60
},
itemHeight:{
type:Number,
default:60
},
gapWidth:{ // 距离边距
type:Number,
default:-20
},
coefficientHeight:{ // 默认停留位置等比高度
type:Number,
default:0.4
},
gapHeight:{ // 移动最小距离底部高度
type:Number,
default:60
}
},
data(){
return{
timer:null,
currentTop:0,
clientWidth:0,
clientHeight:0,
left:0,
top:0,
}
},
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;
},
mounted(){
window.addEventListener('scroll', this.handleScrollStart);
this.$nextTick(()=>{
const div = this.$refs.div;
div.addEventListener("touchstart",()=>{
div.style.transition = 'none';
});
div.addEventListener("touchmove",(e)=>{
if (e.targetTouches.length === 1) {
let touch = event.targetTouches[0];
this.left = touch.clientX - this.itemWidth/2;
this.top = touch.clientY - this.itemHeight/2;
// console.log(this.top,this.clientHeight)
// console.log(touch)
}
});
div.addEventListener("touchend",()=>{
div.style.transition = 'all 0.3s';
if(this.left>this.clientWidth/2){ // 右边
this.left = this.clientWidth - this.itemWidth;
setTimeout(()=>{ // 停止移动动画
this.left = this.left - this.gapWidth;
},500);
}else{ // 左边
// this.left = this.gapWidth;
this.left = 0;
setTimeout(()=>{ // 停止移动动画
this.left = this.left + this.gapWidth;
},500);
}
if(this.top > this.clientHeight-this.gapHeight){ // 底部位置限制
this.top = this.clientHeight-this.gapHeight*2;
}
if(this.top < 0 ){ // 滑动到头部位置限制
this.top = 0;
}
});
});
},
beforeDestroy(){
window.removeEventListener('scroll', this.handleScrollStart);
},
methods:{
gtouchstart(){
//真正长按后应该执行的内容
console.log("长按事件触发发");
},
//如果手指有移动,则取消所有事件,此时说明用户只是要移动而不是长按
gtouchmove(){
// console.log('移动')
this.$emit('scrollStart');
// this.handleScrollStart();
// alert("取消了");
},
//手释放,如果在500毫秒内就释放,则取消长按事件,此时可以执行onclick应该执行的事件
gtouchend(){
// console.log('9933')
this.$emit('scrollEnd')
console.log("释放");
},
onBtnClicked(){
this.$emit("onFloatBtnClicked");
// console.log('0003')
},
handleScrollStart(){ // 上下滑动时 背部滑动时触发。但这个会有问题。所以背景页面样式需要加 overflow-y: auto; 防止滑动触发背景页面滑动
this.timer&&clearTimeout(this.timer);
this.timer = setTimeout(()=>{
this.handleScrollEnd();
},300);
this.currentTop = document.documentElement.scrollTop || document.body.scrollTop;
console.log('移动',this.currentTop)
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;
}
if(this.top > this.clientHeight-this.gapHeight){
this.top = this.clientHeight-this.gapHeight*2;
}
clearTimeout(this.timer);
}
}
}
}
</script>
<style lang="less" scoped>
.ys-float-btn{
// background:rgb(255,255,255);
// box-shadow:0 2px 10px 0 rgba(0,0,0,0.1);
// border-radius:50%;
// color: #666666;
z-index: 20;
transition: all 0.3s;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: fixed;
// bottom: 20vw;
// img{
// width: 50%;
// height: 50%;
// object-fit: contain;
// margin-bottom: 3px;
// }
// p{
// font-size:7px;
// }
}
</style>
发现原生的方法 在苹果下面 滑动的时候会闪动,不顺畅
改成
<template>
<div class="ys-float-btn" :style="{'width':itemWidth+'px','height':itemHeight+'px','left':left+'px','top':top+'px'}"
ref="div"
@touchstart.stop="gtouchstart"
@touchmove.stop="gtouchmove"
@touchend.stop="gtouchend"
@click.stop ="onBtnClicked">
<slot></slot>
<!-- <p>{{text}}</p> -->
</div>
</template>
<script>
export default {
name: "FloatImgBtn",
props:{
// 背景页面需要设置宽度。或者滑动不会顺畅
itemWidth:{
type:Number,
default:60
},
itemHeight:{
type:Number,
default:60
},
gapWidth:{ // 距离边距
type:Number,
default:-25
},
coefficientHeight:{ // 默认停留位置等比高度
type:Number,
default:0.4
},
gapHeight:{ // 移动最小距离底部高度
type:Number,
default:60
},
timeWidth:{ // 半隐藏延迟时间 毫秒
type:Number,
default: 1500
}
},
data(){
return{
timer:null,
currentTop:0,
clientWidth:0,
clientHeight:0,
left:0,
top:0,
}
},
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;
},
mounted(){
// window.addEventListener('scroll', this.handleScrollStart);
// this.$nextTick(()=>{
// const div = this.$refs.div;
// div.addEventListener("touchstart",()=>{
// // div.style.transition = 'none';
// });
// div.addEventListener("touchmove",(e)=>{
// if (e.targetTouches.length === 1) {
// let touch = event.targetTouches[0];
// this.left = touch.clientX - this.itemWidth/2;
// this.top = touch.clientY - this.itemHeight/2;
// // console.log(this.top,this.clientHeight)
// console.log('移动2')
// }
// });
// div.addEventListener("touchend",()=>{
// // div.style.transition = 'all 0.3s';
// console.log('停止2')
// alert('停止3')
// if(this.left>this.clientWidth/2){ // 右边
// this.left = this.clientWidth - this.itemWidth;
// // setTimeout(()=>{ // 停止移动动画
// // this.left = this.left - this.gapWidth;
// // },this.timeWidth);
// }else{ // 左边
// // this.left = this.gapWidth;
// this.left = 0;
// // setTimeout(()=>{ // 停止移动动画
// // this.left = this.left + this.gapWidth;
// // },this.timeWidth);
// }
// if(this.top > this.clientHeight-this.gapHeight){ // 底部位置限制
// this.top = this.clientHeight-this.gapHeight*2;
// }
// if(this.top < 0 ){ // 滑动到头部位置限制
// this.top = 0;
// }
// });
// });
},
beforeDestroy(){
// window.removeEventListener('scroll', this.handleScrollStart);
},
methods:{
gtouchstart(){
//真正长按后应该执行的内容
let div = this.$refs.div;
div.style.transition = 'none';
console.log("长按事件触发发");
},
//如果手指有移动,则取消所有事件,此时说明用户只是要移动而不是长按
gtouchmove(e){
console.log('移动',e)
if (e.targetTouches.length === 1) {
let touch = e.targetTouches[0];
this.left = touch.clientX - this.itemWidth/2;
this.top = touch.clientY - this.itemHeight/2;
// console.log(this.top,this.clientHeight)
console.log('移动2')
}
this.$emit('scrollStart');
// this.handleScrollStart();
// alert("取消了");
},
//手释放,如果在500毫秒内就释放,则取消长按事件,此时可以执行onclick应该执行的事件
gtouchend(){
// console.log('9933')
this.$emit('scrollEnd')
let div = this.$refs.div;
div.style.transition = 'all 0.3s';
if(this.left>this.clientWidth/2){ // 右边
this.left = this.clientWidth - this.itemWidth;
setTimeout(()=>{ // 停止移动动画
this.left = this.left - this.gapWidth;
},this.timeWidth);
}else{ // 左边
// this.left = this.gapWidth;
this.left = 0;
setTimeout(()=>{ // 停止移动动画
this.left = this.left + this.gapWidth;
},this.timeWidth);
}
if(this.top > this.clientHeight-this.gapHeight){ // 底部位置限制
this.top = this.clientHeight-this.gapHeight*2;
}
if(this.top < 0 ){ // 滑动到头部位置限制
this.top = 0;
}
},
onBtnClicked(){
this.$emit("onFloatBtnClicked");
// console.log('0003')
},
handleScrollStart(){ // 上下滑动时 背部滑动时触发。但这个会有问题。所以背景页面样式需要加 overflow-y: auto; 防止滑动触发背景页面滑动
this.timer&&clearTimeout(this.timer);
this.timer = setTimeout(()=>{
this.handleScrollEnd();
},300);
this.currentTop = document.documentElement.scrollTop || document.body.scrollTop;
console.log('移动',this.currentTop)
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;
}
if(this.top > this.clientHeight-this.gapHeight){
this.top = this.clientHeight-this.gapHeight*2;
}
clearTimeout(this.timer);
}
}
}
}
</script>
<style lang="less" scoped>
.ys-float-btn{
// background:rgb(255,255,255);
// box-shadow:0 2px 10px 0 rgba(0,0,0,0.1);
// border-radius:50%;
// color: #666666;
z-index: 20;
transition: all 0.3s;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
position: fixed;
// bottom: 20vw;
// img{
// width: 50%;
// height: 50%;
// object-fit: contain;
// margin-bottom: 3px;
// }
// p{
// font-size:7px;
// }
}
</style>
背景页面引用
<float>
<a
:href="xxxx"
>
<img src="../assets/tpjia.png" style="width: 1rem;" alt />
</a>
</float>
import float from "@/components/float";
components: {
float
},
需要注意,背景页面样式。否则会导致 拖动图标的时候 ,影响背景页面滑动
.index-body {
position: absolute;
overflow-y: auto;
// left: 0.3rem;
// 此样式会影响浮标滑动,需要设置宽度
width: calc(100% - 0.6rem);
top: 0;
bottom: 0;
// right: 0.3rem;
// padding-bottom: 1.2rem;
padding-left: 0.3rem;
padding-right: 0.3rem;
background: #FAFAFA;
}
滑动页面。第一个overflow-y: auto; 值语序Y轴。 可以避免拖动浮标时,影响背景滑动
width: calc(100% - 0.6rem); 需要设置宽度,组件计算滑动,和距离。如果没有设置会有影响