前端实战:实现块级元素的拖拽与缩放功能

在现代网页开发中,用户交互是一个非常重要的部分。在这篇文章中,我们将详细介绍如何使用原生 JavaScript 实现块级元素的拖拽与缩放功能。具体来说,我们将实现以下功能:

  1. 点击并拖动 outer 元素,可以移动整个块。
  2. 点击并拖动 inner 元素,可以调整 outer 元素的宽高。
    在这里插入图片描述

实现思路

为了实现上述功能,我们需要对两个元素分别进行事件监听和处理。具体来说,我们需要监听 mousedownmousemovemouseup 事件,并根据事件触发的位置和元素的状态,来决定执行拖动还是缩放操作。

HTML 结构

首先,我们定义两个块元素 outerinnerinner 位于 outer 的右下角,用于调整 outer 的大小。

<div id="outer" style="width: 100px; height: 100px; border: 1px solid black; position: relative;">
    <span id="inner" style="position: absolute; bottom: 0; right: 0; width: 10px; height: 10px; background: red; cursor: nwse-resize;"></span>
</div>

在这里插入图片描述

CSS 样式

简单的样式来定义块元素的尺寸和位置:

#outer {
    width: 100px;
    height: 100px;
    border: 1px solid black;
    position: relative;
}

#inner {
    position: absolute;
    bottom: 0;
    right: 0;
    width: 10px;
    height: 10px;
    background: red;
    cursor: nwse-resize;
}

JavaScript 实现

接下来,我们编写 JavaScript 代码,实现块的拖动和缩放功能。我们需要两个主要的事件处理程序,一个用于 outer 的拖动,另一个用于 inner 的缩放。

拖动功能

首先实现 outer 的拖动功能:

document.addEventListener('DOMContentLoaded', function() {
    const outer = document.getElementById('outer');
    let isDragging = false;
    let dragStartX, dragStartY, startLeft, startTop;

    outer.addEventListener('mousedown', function(e) {
        if (e.target === outer) {
            isDragging = true;
            dragStartX = e.clientX;
            dragStartY = e.clientY;
            startLeft = outer.offsetLeft;
            startTop = outer.offsetTop;
            document.addEventListener('mousemove', drag);
            document.addEventListener('mouseup', stopDrag);
        }
    });

    function drag(e) {
        if (isDragging) {
            const dx = e.clientX - dragStartX;
            const dy = e.clientY - dragStartY;
            outer.style.left = `${startLeft + dx}px`;
            outer.style.top = `${startTop + dy}px`;
        }
    }

    function stopDrag() {
        isDragging = false;
        document.removeEventListener('mousemove', drag);
        document.removeEventListener('mouseup', stopDrag);
    }
});

以下是实现拖动效果,此时还未实现缩放功能。
在这里插入图片描述

缩放功能

接下来实现 inner 的缩放功能:

document.addEventListener('DOMContentLoaded', function() {
    const outer = document.getElementById('outer');
    const inner = document.getElementById('inner');
    let isResizing = false;
    let resizeStartX, resizeStartY, startWidth, startHeight;

    inner.addEventListener('mousedown', function(e) {
        e.stopPropagation(); // 阻止事件冒泡到 outer
        isResizing = true;
        resizeStartX = e.clientX;
        resizeStartY = e.clientY;
        startWidth = outer.offsetWidth;
        startHeight = outer.offsetHeight;
        document.addEventListener('mousemove', resize);
        document.addEventListener('mouseup', stopResize);
    });

    function resize(e) {
        if (isResizing) {
            const dx = e.clientX - resizeStartX;
            const dy = e.clientY - resizeStartY;
            outer.style.width = `${startWidth + dx}px`;
            outer.style.height = `${startHeight + dy}px`;
        }
    }

    function stopResize() {
        isResizing = false;
        document.removeEventListener('mousemove', resize);
        document.removeEventListener('mouseup', stopResize);
    }
});

组合功能

为了确保两个功能可以同时存在,我们需要确保在 inner 被拖动时,outer 的拖动功能不会被触发。为此,我们在 innermousedown 事件处理程序中调用 e.stopPropagation(),以阻止事件冒泡到 outer

完整代码

以下是完整的实现代码,包括 HTML、CSS 和 JavaScript 部分:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>拖拽与缩放功能</title>
    <style>
        #outer {
            width: 100px;
            height: 100px;
            border: 1px solid black;
            position: absolute;
        }

        #inner {
            position: absolute;
            bottom: 0;
            right: 0;
            width: 10px;
            height: 10px;
            background: red;
            cursor: nwse-resize;
        }
    </style>
</head>
<body>
    <div id="outer">
        <span id="inner"></span>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            const outer = document.getElementById('outer');
            const inner = document.getElementById('inner');
            let isDragging = false;
            let isResizing = false;
            let dragStartX, dragStartY, startLeft, startTop;
            let resizeStartX, resizeStartY, startWidth, startHeight;

            outer.addEventListener('mousedown', function(e) {
                if (e.target === outer) {
                    isDragging = true;
                    dragStartX = e.clientX;
                    dragStartY = e.clientY;
                    startLeft = outer.offsetLeft;
                    startTop = outer.offsetTop;
                    document.addEventListener('mousemove', drag);
                    document.addEventListener('mouseup', stopDrag);
                }
            });

            inner.addEventListener('mousedown', function(e) {
                e.stopPropagation(); // 阻止事件冒泡到 outer
                isResizing = true;
                resizeStartX = e.clientX;
                resizeStartY = e.clientY;
                startWidth = outer.offsetWidth;
                startHeight = outer.offsetHeight;
                document.addEventListener('mousemove', resize);
                document.addEventListener('mouseup', stopResize);
            });

            function drag(e) {
                if (isDragging) {
                    const dx = e.clientX - dragStartX;
                    const dy = e.clientY - dragStartY;
                    outer.style.left = `${startLeft + dx}px`;
                    outer.style.top = `${startTop + dy}px`;
                }
            }

            function stopDrag() {
                isDragging = false;
                document.removeEventListener('mousemove', drag);
                document.removeEventListener('mouseup', stopDrag);
            }

            function resize(e) {
                if (isResizing) {
                    const dx = e.clientX - resizeStartX;
                    const dy = e.clientY - resizeStartY;
                    outer.style.width = `${startWidth + dx}px`;
                    outer.style.height = `${startHeight + dy}px`;
                }
            }

            function stopResize() {
                isResizing = false;
                document.removeEventListener('mousemove', resize);
                document.removeEventListener('mouseup', stopResize);
            }
        });
    </script>
</body>
</html>

总结

通过本文的介绍和代码示例,我们成功实现了使用原生 JavaScript 实现块级元素的拖拽与缩放功能。在实际开发中,这种交互功能非常常见,并且对于提升用户体验非常有帮助。希望本文能够帮助你更好地理解事件处理和 DOM 操作。如果你有任何问题或建议,欢迎交流讨论。

  • 30
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值