Vue实现一个可以拖拽的工具栏

最近一直在做编辑器的小项目,怎么说呢?一个看起来非常简单的小工具也需要大量的巧思和优化。

其实我发现随随便便的一个小工具都有重新做一遍的价值,一来是符合新的使用习惯,二来新的UI风格也更顺眼。

现在AI编程真的是"害人不浅",比较难的功能随手Trea一下,直接代码就写好了,这简直是程序员的"盛夏"。

编辑器的过程中发现一个复制的功能,放在工具栏需要两步操作,点击工具,然后再点击复制到哪个平台

还是放出来比较合适,但是放在外层又有点儿遮挡,所以做了一个可以拖拽的工具栏。

源码

html 复制代码
<template>
    <div class="tool-copy-container" :style="toolPosition">
        <!-- 拖拽部分 -->
        <div class="tool-copy-drag" @mousedown="startDragging">
            <i class="iconfont icon-drag"></i>
        </div>

        <div class="tool-copy-item" v-for="(item, index) in tools" :key="index">
            <el-tooltip
                class="box-item"
                effect="dark"
                :content="'复制到' + item.name"
                placement="left"
            >
                <i class="iconfont" :class="item.icon" :style="{color: item.color}"></i>
            </el-tooltip>
        </div>
    </div>
</template>

<script setup>
import { reactive, ref } from "vue";

// 工具列表数据
const tools = reactive([
    {
        name: '公众号',
        title: 'wechat',
        icon: 'icon-wechat',
        color: '#07C874'
    },
    ......
]);

// 初始位置
const toolPosition = reactive({
    top: '300px',
    right: '20px'
});

// 拖拽相关状态
// 定义一个响应式的布尔变量,用于追踪是否正在拖动
const isDragging = ref(false);
// 定义一个响应式的对象,用于存储拖动偏移量
const dragOffset = reactive({
    x: 0,
    y: 0
});

/**
 * 开始拖动的函数
 * @param {MouseEvent} event - 触发的鼠标事件
 */
function startDragging(event) {
    isDragging.value = true;

    // 获取目标元素的位置信息
    const rect = event.target.getBoundingClientRect();
    // 计算鼠标点击位置相对于元素左上角的偏移量
    dragOffset.x = event.clientX - rect.left;
    dragOffset.y = event.clientY - rect.top;

    // 添加鼠标移动和释放事件监听器
    document.addEventListener('mousemove', onMouseMove);
    document.addEventListener('mouseup', onMouseUp);
}

/**
 * 鼠标移动时的处理函数
 * @param {MouseEvent} event - 触发的鼠标事件
 */
function onMouseMove(event) {
    if (!isDragging.value) return;

    // 计算新的鼠标位置,并减去初始偏移量
    const x = event.clientX - dragOffset.x;
    const y = event.clientY - dragOffset.y;

    // 设置新的位置
    toolPosition.top = `${y}px`;
    toolPosition.right = `${window.innerWidth - (x + rect().width)}px`;

    // 禁止文本选择,防止用户在拖动时选择页面内容
    document.body.style.userSelect = 'none';
}

/**
 * 鼠标释放时的处理函数
 */
function onMouseUp() {
    isDragging.value = false;
    // 移除鼠标移动和释放事件监听器
    document.removeEventListener('mousemove', onMouseMove);
    document.removeEventListener('mouseup', onMouseUp);
    // 恢复文本选择,允许用户选择页面内容
    document.body.style.userSelect = '';
}

/**
 * 获取工具容器的尺寸信息
 * @returns {DOMRect} - 元素的尺寸信息,如果没有找到元素则返回 { width: 0 }
 */
function rect() {
    const el = document.querySelector('.tool-copy-container');
    return el ? el.getBoundingClientRect() : { width: 0 };
}

</script>

<style scoped>
.tool-copy-container {
    background-color: #fff;
    border: 1px solid #ddd;
    position: fixed;
    top: 50%;
    right: 20px;
}

.tool-copy-drag {
    width: 100%;
    text-align: center;
    cursor: all-scroll;
}

.tool-copy-item {
    margin: 5px 0;
    text-align: center;
    padding: 0 5px;
    box-sizing: border-box;
    cursor: pointer;
}
</style>

原理

给要移动的DOM一个动态的style,通过绑定mousedown事件来触发拖动。

通过绑定mousemove事件来实时更新DOM位置,通过mouseup事件来结束拖动。

当然,这只是一个Demo,如果想要更好的效果还需要再优化。

Ps: 后期会把做的编辑器开源,希望大家捧场。万分感谢!

相关推荐
wkj0012 小时前
vue中 js-cookie 用法
前端·javascript·vue.js
GoldKey6 小时前
gcc 源码阅读---语法树
linux·前端·windows
Xf3n1an7 小时前
html语法
前端·html
张拭心7 小时前
亚马逊 AI IDE Kiro “狙击”Cursor?实测心得
前端·ai编程
烛阴8 小时前
为什么你的Python项目总是混乱?层级包构建全解析
前端·python
@大迁世界8 小时前
React 及其生态新闻 — 2025年6月
前端·javascript·react.js·前端框架·ecmascript
红尘散仙9 小时前
Rust 终端 UI 开发新玩法:用 Ratatui Kit 轻松打造高颜值 CLI
前端·后端·rust
新酱爱学习9 小时前
前端海报生成的几种方式:从 Canvas 到 Skyline
前端·javascript·微信小程序
袁煦丞9 小时前
把纸堆变数据流!Paperless-ngx让文件管理像打游戏一样爽:cpolar内网穿透实验室第539个成功挑战
前端·程序员·远程工作
慧慧吖@9 小时前
关于两种网络攻击方式XSS和CSRF
前端·xss·csrf