分享一个窗口拖拽功能小扩展

2,132 阅读3分钟

前言

学习编程可以追溯到高中时代,回首望去20多年,有遗憾,因为没能真正从事这方面职业,但是兴趣使然一直没有放弃,大大小小项目也开发过,独立的合作的都有。突发奇想也许我也能写写东西,是分享,也是学习,更是想交朋友。今天分享一个窗口拖拽功能。希望大家喜欢!

正题

先上图

微信截图_20220621185814.png

需要8个方向拖拽与鼠标按住移动,这个功能应该是比较常见的,当然网上的教程很多,不过我还是自己写了一个适合自己的,当然,参考是必不可少的!!

按住拖拽

先上代码

export const PressDrop = (moveTarget: MaybeRef<HTMLElement | null>, target: MaybeRef<HTMLElement | null>) => {
    const onMouseDown = (e: MouseEvent) => {
        e.preventDefault()
        const move = unrefElement(moveTarget)
        const el = unrefElement(target)
        if (!el || !move)
            return
        const distanceX = e.clientX - el.offsetLeft
        const distanceY = e.clientY - el.offsetTop

        document.onmousemove = (e: MouseEvent) => {
            e.preventDefault()
            el.style.left = e.clientX - distanceX + 'px'
            el.style.top = e.clientY - distanceY + 'px'
        }
        document.onmouseup = (e: MouseEvent) => {
            e.preventDefault()
            document.onmousemove = null
            document.onmouseup = null
        }
    }
    if (moveTarget && target) {
        useEventListener(moveTarget, 'mousedown', onMouseDown)
    }
}

moveTarget 是鼠标点击的位置,target是要移动的部分。先注册一个 mousedown 事件 后续也就好说了

8个方向可拖拽



export interface windowDropOptions {
    /**
     * 是否可改变尺寸
     */
    isResize: boolean,
    /**
     * 窗体最大高度
     */
    maxHeight: number,
    /**
     * 窗体最大宽度
     */
    maxWidth: number
}

export const WindowDrop = (target: MaybeRef<HTMLElement | null>, options: windowDropOptions) => {
    const mouse = reactive(useMouseInElement(target))
    /**
     * 主窗体改变尺寸
     * @param e
     */
    const onMainMouseDown = (e: MouseEvent) => {
        const targetRef = ref(target ?? window?.document.body)
        const el = unrefElement(targetRef)
        e.preventDefault()
        if (!el)
            return
        //判断鼠标点击位置
        const maxMargin = 7
        const minMargin = -10
        const mY = mouse.elementY
        const mX = mouse.elementX
        const xW = Math.abs(mouse.elementX - mouse.elementWidth)
        const yH = Math.abs(mouse.elementY - mouse.elementHeight)
        let disV = [0, 0]
        //top
        if (mY >= minMargin && mY <= maxMargin && mX >= maxMargin && xW >= maxMargin) {
            disV = [-1, 0]
        }
        //bottom
        if (yH >= minMargin && yH <= maxMargin && mX >= maxMargin && xW >= maxMargin) {
            disV = [1, 0]
        }
        //left
        if (mX >= minMargin && mX <= maxMargin && mY >= maxMargin && yH >= maxMargin) {
            disV = [0, -1]
        }
        //right
        if (xW >= minMargin && xW <= maxMargin && mY >= maxMargin && yH >= maxMargin) {
            disV = [0, 1]
        }
        //left-top
        if (mX >= minMargin && mX <= maxMargin && mY >= 0 && mY <= maxMargin) {
            disV = [-1, -1]
        }
        //right-top
        if (xW >= minMargin && xW <= maxMargin && mY >= 0 && mY <= maxMargin) {
            disV = [-1, 1]
        }
        //left-bottom
        if (mX >= minMargin && mX <= maxMargin && yH >= 0 && yH <= maxMargin) {
            disV = [1, -1]
        }
        //right-bottom
        if (xW >= minMargin && xW <= maxMargin && yH >= 0 && yH <= maxMargin) {
            disV = [1, 1]
        }
        if (disV[0] === 0 && disV[1] === 0)
            return
        //鼠标点击位置X坐标
        const disX = mouse.x
        //鼠标点击位置Y坐标
        const disY = mouse.y
        //窗口的位置到顶的距离
        const posT = el.offsetTop
        //窗口的位置到左边的距离
        const posL = el.offsetLeft
        //窗口初始高度
        const disH = el.offsetHeight
        //窗口初始宽度
        const disW = el.offsetWidth
        //设置窗口可调的最小高度
        const minH = 200
        //设置窗口可调的最小宽度
        const minW = 200
        document.onmousemove = (e) => {
            e.preventDefault()
            //鼠标现在的位置
            const nDisX = mouse.x
            const nDisY = mouse.y
            //移动后窗口的高度 //-1 * ( 当前鼠标Y - 鼠标初始位置Y ) + 窗口初始高度
            let disNH = Math.max((disV[0] * (nDisY - disY) + disH), minH)
            //移动后窗口的宽度 // 0 * ( 当前鼠标X - 鼠标初始位置X ) + 窗口初始宽度
            let disNW = Math.max((disV[1] * (nDisX - disX) + disW), minW)
            //移动后窗口顶到顶的距离// *(当前鼠标Y - 鼠标初始位置Y) + 窗口到顶的高度
            let posNT = Math.min(disV[0], 0) * (disNH - disH) + posT
            //移动后窗口到左边的距离//*(当前鼠标X - 鼠标初始位置X) + 窗口到左边的宽度
            let posNL = Math.min(disV[1], 0) * (disNW - disW) + posL
            //设置边界
            posNT = Math.max(posNT, 0)
            disNH = nDisY <= 0 ? disH + posT : disNH
            disNH = nDisY > options.maxHeight ? options.maxHeight - posNT : disNH
            disNW = Math.min(disNW, Math.abs(options.maxWidth - posNL))
            //赋值
            el.style.top = `${posNT}px`
            el.style.left = `${posNL}px`
            el.style.width = `${disNW}px`
            el.style.height = `${disNH}px`
        }
        document.onmouseup = (e) => {
            e.preventDefault()
            document.onmousemove = null
            document.onmouseup = null
        }
    }
    if (target && options.isResize) {
        useEventListener(target, 'mousedown', onMainMouseDown)
    }
    return {
        mouse
    }
}

mouse 使用了vueUse的useMouseInElement,大部分有注释,所以不难理解。首先就是要判段鼠标在目标的位置,然后来判断可拖动的方向(应该有更简洁的写法,可惜我不会,本想合并一下,但没下去手!!!)。默认将鼠标信息返回了,方便调试。

用法

使用起来还是比较简单的

<div ref='el'></div>
-------------------------------
import {PressDrop, WindowDrop} from '@/utils/WindowDrop'
const el = ref(null)
-------------------------------
PressDrop(move, el)  // 窗体移动

/**
 * 改变窗口大小
 */
WindowDrop(el, {isResize: true,maxHeight: 800,maxWidth: 1000})

最后

我应该可以称为非专业的程序员,所有技术全靠自学,纯纯的爱好。我本者不太深究,够用即可的方式,很多东西没学到位,仅够使用。所以以上代码中肯定有很多需要改的地方。这也是首次分享与大家。还请大家批评指正,我会虚心学习。