在Uniapp中,悬浮菜单支持拖动和吸附功能,可以为用户带来更加灵活和便捷的操作体验。以下是对这两个功能的详细解释:
悬浮菜单支持拖动
提高用户体验:用户可以根据自己的需要,将悬浮菜单拖动到屏幕上的任意位置,从而更加便捷地访问和使用菜单中的功能。
灵活性:悬浮菜单的拖动功能使得应用界面更加灵活,用户可以根据自己的使用习惯进行个性化设置。
增强互动性:通过拖动悬浮菜单,用户可以与应用进行更加直观的互动,提高应用的趣味性和互动性。
悬浮菜单支持吸附
自动定位:悬浮菜单在拖动到屏幕边缘时,可以自动吸附在边缘位置,使得菜单更加稳定且不易误操作。
优化布局:吸附功能可以使得悬浮菜单在屏幕上的布局更加合理,避免遮挡其他重要信息或功能按钮。
提升美观度:通过自动吸附,悬浮菜单可以保持与屏幕边缘的一定距离,使得整个应用界面看起来更加整洁、美观。
组件库实现
<template><view:id="id"class="diy-floatbar":style="'left: ' + left + 'px; top:' + top + 'px;'"@touchstart="touchstart"@touchmove.stop.prevent="touchmove"@touchend="touchend"@click.stop.prevent="click":class="{transition: isDock && !isMove }"><slot></slot></view>
</template><script>export default {name: 'diy-floatbar',emits: ["click", "dragStart","dragEnd"],props: {id:{type: String,default: 'floatbar'},//默认位置右下角right-bottom、left-bottom、right-top、left-toppositionType:{type: String,default: 'right-bottom'},//是否吸附isDock:{type: Boolean,default: true},//是否包含底部菜单existTabBar:{type: Boolean,default: false},//默认上下偏移topEdge:{type: Number,default: 50},//默认左右偏移leftEdge:{type: Number,default: 10},//刷新页面后保存不变isDragSave:{type: Boolean,default: false}},data() {return {top:0,left:0,width: 0,height: 0,offsetWidth: 0,offsetHeight: 0,windowWidth: 0,windowHeight: 0,isMove: true,edge: 10,}},mounted() {const sys = uni.getSystemInfoSync();this.windowWidth = sys.windowWidth;this.windowHeight = sys.windowHeight;// #ifdef APP-PLUSthis.existTabBar && (this.windowHeight -= 50);// #endifif (sys.windowTop) {this.windowHeight += sys.windowTop;}let windowTop = 0;if (sys.windowTop) {windowTop = sys.windowTop;}const query = uni.createSelectorQuery().in(this);query.select('#'+this.id).boundingClientRect(data => {this.width = data.width;this.height = data.height;this.offsetWidth = data.width / 2;this.offsetHeight = data.height / 2;let left = 0;let top = 0;if(this.positionType=='right-bottom'){left = this.windowWidth - this.width - this.leftEdge;top = this.windowHeight - this.height - this.topEdge;}else if(this.positionType=='left-bottom'){left = this.leftEdge;top = this.windowHeight - this.height - this.topEdge;}else if(this.positionType=='right-top'){left = this.windowWidth - this.width - this.leftEdge;top = this.topEdge+windowTop;}else if(this.positionType=='left-top'){left = this.leftEdge;top = this.topEdge+windowTop;}if(this.isDragSave){let position = uni.getStorageSync(this.id);if(position){left = position.lefttop = position.top}}this.left = leftthis.top = top}).exec();},methods: {click() {this.$emit('btnClick');},touchstart(e) {this.$emit('dragStart');},touchmove(e) {// 单指触摸if (e.touches.length !== 1) {return false;}this.isMove = true;this.left = e.touches[0].clientX - this.offsetWidth;let clientY = e.touches[0].clientY - this.offsetHeight;// #ifdef H5clientY += this.height;// #endiflet edgeBottom = this.windowHeight - this.height - this.edge;// 上下触及边界if (clientY < this.edge) {this.top = this.edge;} else if (clientY > edgeBottom) {this.top = edgeBottom;} else {this.top = clientY}},touchend(e) {if (this.isDock) {let edgeRigth = this.windowWidth - this.width - this.edge;if (this.left < this.windowWidth / 2 - this.offsetWidth) {this.left = this.edge;} else {this.left = edgeRigth;}}if(this.isDragSave){uni.setStorageSync(this.id,{left:this.left,top:this.top})}this.isMove = false;this.$emit('dragEnd');},}}
</script><style lang="scss">.diy-floatbar {display: flex;justify-content: center;align-items: center;position: fixed;z-index: 999999;&.transition {transition: left .3s ease,top .3s ease;}}</style>
组件库调用
<template><view class="container container329152"><diy-floatbar :topEdge="50" :leftEdge="10" id="floatbar" :isDock="false" :isDragSave="true" positionType="right-bottom"><view class="flex diygw-col-0 right-bottom floatbar-clz"><view class="diygw-grid diygw-actions"><button class="diygw-action"><view class="diygw-grid-inner"><view class="diygw-grid-icon diygw-avatar"><image mode="aspectFit" class="diygw-avatar-img" src="/static/global/grid1.png"></image></view><view class="diygw-grid-title"> 菜单一 </view></view></button></view></view></diy-floatbar><view class="clearfix"></view></view>
</template><script>export default {data() {return {//用户全局信息userInfo: {},//页面传参globalOption: {},//自定义全局变量globalData: { logintype: '0', agree: '0' }};},onShow() {this.setCurrentPage(this);},onLoad(option) {this.setCurrentPage(this);if (option) {this.setData({globalOption: this.getOption(option)});}this.init();},methods: {async init() {}}};
</script><style lang="scss" scoped>.floatbar-clz {bottom: 100rpx;width: 80rpx !important;right: 20rpx;}.floatbar-clz {width: auto !important;height: auto !important;position: initial !important;right: initial !important;left: initial !important;}.container329152 {width: 750rpx !important;margin: 0 auto;}
</style>