uniapp 微信小程序Vue3项目使用内置组件movable-area封装悬浮可拖拽按钮(拖拽结束时自动吸附到最近的屏幕边缘)
一、最终效果
二、具体详情请看movable-area与movable-view官方文档说明
三、参数配置
1、代码示例
<TFab title="新建订单" @click="addOrder" />
// title:表按钮文案
// addOrder:点击按钮事件
四、组件源码
<template><movable-area class="movable-area" @touchend="onTouchend"><movable-view class="movable-view" :x="x" :y="y" direction="all" @change="onChange"><view class="addBtn" :style="{ width: `${width}px` , height: `${height}px`}" @tap="handleClick">{{title}}</view><slot /></movable-view></movable-area>
</template><script lang="ts" setup>
import { debounce } from "@/utils";
defineProps({title: {type: String},width: {type: Number,default: 40},height: {type: Number,default: 40}
});
const emits = defineEmits(["click"]);
const x = ref(0);
const y = ref(0);
const screenWidth = ref(0);
const screenHeight = ref(0);onMounted(() => {uni.getSystemInfo({success: res => {screenWidth.value = res.windowWidth;screenHeight.value = res.windowHeight;// 初始位置在屏幕右下角y.value = screenHeight.value - 200;x.value = screenWidth.value - 70;}});
});
// 拖动坐标更新(防抖)
const onChange = (e: { detail: { x: number; y: number } }) => {debounce(() => {x.value = e.detail.x;y.value = e.detail.y;}, 500);
};
// 触摸结束时吸附边缘
const onTouchend = () => {nextTick(() => {const threshold = 50; // 吸附阈值(rpx)if (Math.abs(x.value - 0) < threshold) {x.value = 0;} else if (Math.abs(x.value - screenWidth.value) < threshold) {x.value = screenWidth.value;}if (Math.abs(y.value - 0) < threshold) {y.value = 0;} else if (Math.abs(y.value - screenHeight.value) < threshold) {y.value = screenHeight.value;}});
};
const handleClick = () => {emits("click");
};
</script><style lang="scss">
.movable-area {position: fixed;top: 0;left: 0;width: 100vw;height: calc(100vh - 100px); // 可根据自己的项目来计算pointer-events: none; /* 关键样式 */z-index: 9999;.movable-view {pointer-events: auto; /* 关键样式 */width: 100rpx;height: 100rpx;will-change: transform;.addBtn {border-radius: 50%;width: 40px;height: 40px;overflow: hidden;display: flex;justify-content: center;align-items: center;color: #fff;font-size: 14px;padding: 8px;box-shadow: 0 1px 5px 2px rgba(0, 0, 0, 0.3);background: #355db4;text-align: center;}}
}
</style>
相关文章
基于ElementUi再次封装基础组件文档
vue3+ts基于Element-plus再次封装基础组件文档