vue3 按住ctrl实现拖拽

<template>
    <div id="equipmentDeployment">
        <div class="data">
            {{ data }} {{ selected }}
        </div>
        <div class="container">
            <div 
                class="row" 
                v-for="row in data" 
                :class="{ 'enter': enterId === row.id }"
                @mouseover="handleMouseOver(row)" 
                @mouseleave="handleMouseLeave(row)">
                <div 
                    class="col" 
                    v-for="col in row.children ?? []" 
                    :id="col.id"
                    :class="{ selected: selected.has(col.id) }"
                    @click="handleClickItem(col)"
                    @mousedown="handleMouseDown(col)">
                        {{ col.id }}
                </div>
            </div>
            <div ref="draggingDom" v-show="dragging" class="draggingDom row" :style="draggingStyle"></div>
        </div>
    </div>
</template>

<script setup>
import { onMounted, onUnmounted } from "vue";
const data = $ref(
    new Array(10).fill(0).map((_, i) => ({
        id: "id" + i,
        children: new Array(3).fill(0).map((_, j) => ({ id: "id" + i + "_" + j })),
    }))
);
const dataMapById = $ref({});
const parentMap = $computed(() => {
    const map = {};
    generatorDataMap(data, (item) => {
        item?.children?.forEach((child) => {
            map[child.id] = item;
        });
    });
    return map;
});
const generatorDataMap = (arr, fn) => {
    arr.forEach((item) => {
        fn(item);
        item.children?.length && generatorDataMap(item.children, fn);
    });
};
generatorDataMap(data, (item) => (dataMapById[item.id] = item));

const selected = $ref(new Set());

let dragging = false;
let isCtrl = false;

let enterId = $ref(null);
let event = $ref(null);
const draggingDom = $ref(null);

const draggingStyle = $computed(() => ({
    left: event?.x - 50 + "px",
    top: event?.y - 50 + "px",
}));

onMounted(() => {
    document.onkeydown = null;
    document.onkeyup = null;
    addKeyEvent();
});

onUnmounted(() => {
    dispose(); 
});

const addKeyEvent = () => {
    // 键盘按下事件
    document.onkeydown = (e) => {
        // 取消默认事件
        e.preventDefault();
        //事件对象兼容
        let e1 = e || event || window.event || arguments.callee.caller.arguments[0]
        //键盘按键判断:左箭头-37;上箭头-38;右箭头-39;下箭头-40  回车:13   ctrl:17   shift:16
        switch (e1.keyCode) {
            case 17:
                isCtrl = true;
                break;
        }
    }
    // 键盘抬起事件
    document.onkeyup = (e) => {
        // 取消默认事件
        e.preventDefault();
        //事件对象兼容
        let e1 = e || event || window.event || arguments.callee.caller.arguments[0]
        switch (e1.keyCode) {
            case 17:
                isCtrl = false;
                break;
        }
    }
};

const handleClickItem = (item) => {
    if(!isCtrl) return;
    selected.has(item.id)? selected.delete(item.id) : selected.add(item.id);
};

const generatorDraggingDom = () => {
    [...selected].forEach((id) => {
        const dom = document.querySelector("#" + id);
        draggingDom.appendChild(dom.cloneNode(true));
    });
};

const handleMouseMove = (e) => {
    if (!dragging) return;
    event = e;
};

const handleMouseUp = (e) => {
    window.removeEventListener("mouseup", handleMouseUp);
    window.removeEventListener("mousemove", handleMouseMove);
    Array.from(draggingDom.children).forEach((childDom) => draggingDom.removeChild(childDom));
    dragging = false;
    event = null;
    
    if(!enterId) return;
    handleDrop();
    enterId = "";
    
    
};

const handleMouseDown = (data) => {
    if (!selected.has(data.id) || isCtrl) return;
    dragging = true;
    window.addEventListener("mouseup", handleMouseUp);
    window.addEventListener("mousemove", handleMouseMove);
    generatorDraggingDom();
};

const handleMouseOver = (data) => {
    if (!dragging) return;
    enterId = data.id;
};

const handleMouseLeave = (e) => {
    if (!dragging) return;
    enterId = "";
};

const handleDrop = () => {
    [...selected].forEach((id) => {
        const parent = parentMap[id];
        const idx = parent.children.findIndex((child) => child.id === id);
        parent.children.splice(idx, 1);
        dataMapById[enterId].children?.push(dataMapById[id]);
    });
    selected.clear()
};

const dispose = () => {
    window.removeEventListener("mouseup", handleMouseUp);
    window.removeEventListener("mousemove", handleMouseMove);
};
</script>

<style lang="scss" scoped>
#equipmentDeployment {
    width: 100%;
    height: 100%;
    overflow: auto !important;
    display: flex;
    gap: 12px;
    user-select: none;
    color: #fff;

    .data {
        width: 200px;
    }

    .container {
        flex: 1;
        display: flex;
        gap: 12px;
        flex-direction: column;

        .row {
            display: flex;
            padding: 8px;
            gap: 8px;
            min-height: 104px;
            border: 1px solid #ccc;

            &.enter {
                background: orange;
            }

            .col {
                cursor: pointer;
                width: 100px;
                height: 100px;
                display: flex;
                justify-content: center;
                align-items: center;
                border: 1px solid #ccc;

                &.selected {
                    border-color: green;
                    color: green;
                }
            }
        }

        .draggingDom {
            position: fixed;
            pointer-events: none;
        }
    }
}
</style>

vue前端html页面中添加鼠标悬停位置按住ctrl 滚轮放大并拖拽的功能,可以通过以下步骤实现: 1. 给页面需要缩放和拖拽的区域添加一个唯一的ID,例如:`<div id="zoomable">...</div>`。 2.Vue的mounted()方法中,使用jQuery或原生JavaScript获取该区域的DOM节点,并添加鼠标事件监听器。 3. 监听鼠标滚轮事件,在滚轮事件触发时,检查是否同时按下了Ctrl键,如果是,则执行缩放操作。 4. 监听鼠标按下和移动事件,在按下事件触发时,检查是否同时按下了Ctrl键,如果是,则执行拖拽操作,移动事件中更新拖拽位置。 下面是一个简单的代码示例,实现Vue前端html页面中添加鼠标悬停位置按住ctrl 滚轮放大并拖拽的功能: ``` <template> <div id="zoomable" @wheel.prevent="onMouseWheel" @mousedown="onMouseDown" @mousemove="onMouseMove" @mouseup="onMouseUp"> <!-- 可缩放和拖拽的内容区域 --> </div> </template> <script> import $ from &#39;jquery&#39; export default { mounted () { const zoomable = document.getElementById(&#39;zoomable&#39;) let isDragging = false let dragStartX, dragStartY, offsetX = 0, offsetY = 0 let zoomLevel = 1 $(zoomable).on(&#39;wheel&#39;, event => { if (event.ctrlKey) { event.preventDefault() zoomLevel += event.originalEvent.deltaY > 0 ? -0.1 : 0.1 zoomable.style.transform = `scale(${zoomLevel}) translate(${offsetX}px, ${offsetY}px)` } }) $(zoomable).on(&#39;mousedown&#39;, event => { if (event.ctrlKey) { isDragging = true dragStartX = event.clientX dragStartY = event.clientY } }) $(zoomable).on(&#39;mousemove&#39;, event => { if (isDragging) { offsetX += event.clientX - dragStartX offsetY += event.clientY - dragStartY dragStartX = event.clientX dragStartY = event.clientY zoomable.style.transform = `scale(${zoomLevel}) translate(${offsetX}px, ${offsetY}px)` } }) $(zoomable).on(&#39;mouseup&#39;, event => { isDragging = false }) }, methods: { onMouseWheel (event) { // do nothing, handled by jQuery }, onMouseDown (event) { // do nothing, handled by jQuery }, onMouseMove (event) { // do nothing, handled by jQuery }, onMouseUp (event) { // do nothing, handled by jQuery } } } </script> ``` 在上述代码示例中,我们使用jQuery来监听鼠标事件,实现了缩放和拖拽功能。其中,通过`event.ctrlKey`属性来检查是否同时按下了Ctrl键。在缩放操作中,我们使用`transform`属性来设置缩放和偏移量。在拖拽操作中,我们使用`offsetX`和`offsetY`变量来记录拖拽的偏移量,并在移动事件中更新位置。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值