当前位置:首页 » 《随便一记》 » 正文

打造新Web体验:如何在Vue 2项目中实现可拖动定位的悬浮按钮(代码版)

27 人参与  2024年10月10日 14:00  分类 : 《随便一记》  评论

点击全文阅读



实现屏幕右侧可拖动的悬浮按钮

在现代的前端开发中,悬浮按钮广泛应用于各种场景。本文将介绍如何在 Vue 2 项目中实现一个固定在屏幕右侧、可垂直拖动的悬浮按钮。按钮拖动后会自动固定在屏幕的右侧,避免按钮超出屏幕范围,并配合抽屉组件实现快捷菜单功能。

功能需求

固定在屏幕右侧:按钮始终固定在屏幕的右侧,用户无法水平拖动按钮。垂直拖动:用户可以自由拖动按钮在垂直方向上移动,并限制在屏幕上下边界内。贴边显示:拖动结束后,按钮始终保持贴边显示。抽屉菜单:点击按钮可打开抽屉,展示快捷菜单功能。

实现步骤

1. 创建悬浮按钮组件

首先,创建一个 Vue 组件用于实现悬浮按钮和抽屉功能。我们使用 element-ui 组件库来实现按钮和抽屉,并添加拖动和贴边逻辑。

<template>  <div v-if="shouldShowButton">    <!-- 小箭头按钮,控制悬浮按钮的显示和隐藏 -->    <div      v-if="!floatingButtonVisible"      class="arrow-button"      @click="toggleFloatingButton"    >      →    </div>    <!-- 悬浮按钮 -->    <transition name="slide-fade">      <el-button        v-if="floatingButtonVisible"        class="floating-button"        type="primary"        circle        @mousedown="startDrag"        @click="toggleDrawer"        :style="{ top: `${buttonPosition.y}px`, right: `20px`, transition: isDragging ? 'none' : 'top 0.3s ease, right 0.3s ease' }"      >        {{ todoCount }}      </el-button>    </transition>    <!-- 抽屉 -->    <el-drawer      v-model="drawerVisible"      direction="rtl"      size="50%"      title="快捷菜单"      @close="toggleDrawer"    >      <!-- 抽屉内容 -->      <el-tabs type="border-card" style="min-height: 500px">        <el-tab-pane label="我的待办" style="height:500px;overflow: auto;">          <!-- 演示表格 -->          <el-table            :cell-style="{'text-align':'center'}"            :data="demoData"            :header-cell-style="{'text-align':'center'}"            border            table-layout="auto"            class="table-style"            highlight-current-row          >            <el-table-column label="示例列1" prop="column1"></el-table-column>            <el-table-column label="示例列2" prop="column2"></el-table-column>          </el-table>        </el-tab-pane>        <el-tab-pane label="已办" style="height:700px;overflow: auto;">          <!-- 演示表格 -->          <el-table            :cell-style="{'text-align':'center'}"            :data="demoData"            :header-cell-style="{'text-align':'center'}"            border            table-layout="auto"            highlight-current-row            class="table-style"          >            <el-table-column label="示例列1" prop="column1"></el-table-column>            <el-table-column label="示例列2" prop="column2"></el-table-column>          </el-table>        </el-tab-pane>      </el-tabs>    </el-drawer>  </div></template><script>export default {  data() {    return {      drawerVisible: false,      floatingButtonVisible: true,      todoCount: 5, // 代办事项数量      isDragging: false,      buttonPosition: { y: window.innerHeight - 70 }, // 初始位置:右下角      startY: 0,      demoData: [        { column1: "示例数据1", column2: "示例数据2" },        { column1: "示例数据3", column2: "示例数据4" },      ], // 演示数据    };  },  computed: {    shouldShowButton() {      return !this.$route.path.includes("/login");    },  },  mounted() {    // 监听窗口大小变化    window.addEventListener("resize", this.updateButtonPosition);  },  beforeDestroy() {    // 在组件销毁时移除监听器    window.removeEventListener("resize", this.updateButtonPosition);  },  methods: {    toggleDrawer() {      this.drawerVisible = !this.drawerVisible;    },    toggleFloatingButton() {      this.floatingButtonVisible = !this.floatingButtonVisible;    },    startDrag(event) {      this.isDragging = true;      this.startY = event.clientY - this.buttonPosition.y;      document.addEventListener("mousemove", this.onDrag);      document.addEventListener("mouseup", this.stopDrag);    },    onDrag(event) {      if (this.isDragging) {        // 只允许垂直移动,限制范围在屏幕内        let newY = event.clientY - this.startY;        newY = Math.max(0, Math.min(newY, window.innerHeight - 50));        this.buttonPosition.y = newY;      }    },    stopDrag() {      this.isDragging = false;      document.removeEventListener("mousemove", this.onDrag);      document.removeEventListener("mouseup", this.stopDrag);    },    updateButtonPosition() {      // 当窗口调整大小时更新按钮位置,确保按钮不超出屏幕      this.buttonPosition.y = Math.min(this.buttonPosition.y, window.innerHeight - 50);    },  },};</script><style scoped>.floating-button {  position: fixed;  z-index: 1000;  display: flex;  justify-content: center;  align-items: center;  width: 50px;  height: 50px;  border-radius: 50%;  transition: top 0.3s ease, right 0.3s ease;  cursor: pointer;  right: 20px; /* 固定在右侧 */}.arrow-button {  position: fixed;  right: 0;  bottom: 20px;  z-index: 1000;  width: 20px;  height: 50px;  background-color: #409eff;  color: white;  display: flex;  justify-content: center;  align-items: center;  border-radius: 0 10px 10px 0;  cursor: pointer;}.slide-fade-enter-active,.slide-fade-leave-active {  transition: all 0.3s ease;}.slide-fade-enter,.slide-fade-leave-to {  transform: translateX(100%);  opacity: 0;}</style>

2. 实现逻辑说明

固定右侧贴边: 悬浮按钮始终固定在屏幕右侧(通过 right: 20px;),用户无法水平拖动按钮,仅能在垂直方向上移动。

垂直移动: 在 onDrag 方法中,仅允许按钮在 y 轴上移动。通过限制 y 值,确保按钮不会超出屏幕上下边界。

贴边显示: 由于按钮始终固定在右侧,因此在用户停止拖动时按钮自动贴边。

抽屉菜单: 按钮的点击事件触发抽屉菜单的显示或隐藏,并展示了一些演示数据。

窗口大小调整: 在窗口大小发生变化时,通过 updateButtonPosition 方法动态调整按钮位置,确保按钮不会超出屏幕。

3. 总结

通过上述代码和实现逻辑,我们成功创建了一个固定在屏幕右侧且可垂直拖动的悬浮按钮。这个按钮在移动后始终贴边,并且结合抽屉组件实现了快捷菜单功能。在实际应用中,你可以根据项目需求进一步定制和扩展此功能。


希望这篇博客内容能够帮助你理解和实现类似的悬浮按钮功能。如有任何疑问或建议,欢迎在评论区留言讨论!


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/170030.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1