拖拉拽效果加点击事件

javascript 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>自由拖拽+点击元素</title>
    <style>
        body {
            margin: 0;
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            background: #f0f0f0;
        }

        #container {
            width: 800px;
            height: 600px;
            border: 2px dashed #999;
            position: relative;
            overflow: hidden;
        }

        .draggable {
            position: absolute;
            width: 120px;
            height: 120px;
            background: #fff;
            border-radius: 8px;
            box-shadow: 0 2px 10px rgba(0,0,0,0.1);
            cursor: grab;
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            transition: box-shadow 0.2s;
        }

        .draggable.dragging {
            cursor: grabbing;
            box-shadow: 0 5px 15px rgba(0,0,0,0.2);
        }

        .tag {
            padding: 6px 12px;
            background: #4CAF50;
            color: white;
            border-radius: 4px;
            margin-bottom: 8px;
            cursor: pointer;
            transition: background 0.2s;
        }

        .tag:hover {
            background: #45a049;
        }
    </style>
</head>
<body>
    <div id="container">
        <div class="draggable" style="left: 100px; top: 100px">
            <div class="tag">可拖拽标签</div>
            <div class="coordinates">(100, 100)</div>
        </div>
    </div>

    <script>
        (function() {
            // 拖拽系统初始化
            const draggables = document.querySelectorAll('.draggable');
            let currentDraggable = null;
            let startX = 0;
            let startY = 0;
            let initialX = 0;
            let initialY = 0;
            let isClick = true;

            // 鼠标按下事件
            document.addEventListener('mousedown', e => {
                const target = e.target.closest('.draggable');
                if (!target) return;

                currentDraggable = target;
                startX = e.clientX;
                startY = e.clientY;
                initialX = parseFloat(target.style.left) || 0;
                initialY = parseFloat(target.style.top) || 0;
                isClick = true;
                
                target.classList.add('dragging');
                document.addEventListener('mousemove', onMouseMove);
                document.addEventListener('mouseup', onMouseUp);
            });

            // 鼠标移动事件
            function onMouseMove(e) {
                if (!currentDraggable) return;
                
                // 判断是否达到移动阈值(3像素)
                if (Math.abs(e.clientX - startX) > 3 || 
                    Math.abs(e.clientY - startY) > 3) {
                    isClick = false;
                }

                const container = document.getElementById('container');
                const containerRect = container.getBoundingClientRect();
                const elementRect = currentDraggable.getBoundingClientRect();
                
                // 计算新位置
                let newX = initialX + (e.clientX - startX);
                let newY = initialY + (e.clientY - startY);

                // 边界限制
                newX = Math.max(0, Math.min(
                    newX, 
                    containerRect.width - elementRect.width
                ));
                
                newY = Math.max(0, Math.min(
                    newY,
                    containerRect.height - elementRect.height
                ));

                // 更新位置
                currentDraggable.style.left = `${newX}px`;
                currentDraggable.style.top = `${newY}px`;
                
                // 更新坐标显示
                currentDraggable.querySelector('.coordinates').textContent = 
                    `(${Math.round(newX)}, ${Math.round(newY)})`;
            }

            // 鼠标松开事件
            function onMouseUp(e) {
                if (!currentDraggable) return;
                
                currentDraggable.classList.remove('dragging');
                document.removeEventListener('mousemove', onMouseMove);
                document.removeEventListener('mouseup', onMouseUp);
                currentDraggable = null;

                // 如果移动距离太小视为点击
                if (isClick) {
                    handleClick(e);
                }
            }

            // 点击处理函数
            function handleClick(e) {
                const tag = e.target.closest('.tag');
                if (tag) {
                    // 标签点击
                    tag.style.background = '#ff5722';
                    setTimeout(() => tag.style.background = '#4CAF50', 200);
                    alert('标签被点击!');
                } else {
                    // 整个元素点击
                    const element = e.target.closest('.draggable');
                    element.style.background = '#f8f8f8';
                    setTimeout(() => element.style.background = '#fff', 200);
                    alert('元素被点击!');
                }
            }
        })();
    </script>
</body>
</html>
相关推荐
叫我詹躲躲1 分钟前
别再用mixin了!Vue3自定义Hooks让逻辑复用爽到飞起
javascript·vue.js
文心快码BaiduComate1 分钟前
Comate Spec模式实测:让AI编程更精准可靠
前端·后端·前端框架
菥菥爱嘻嘻6 分钟前
组件测试--React Testing Library的学习
前端·学习·react.js
豆苗学前端7 分钟前
HTML + CSS 终极面试全攻略(八股文 + 场景题 + 工程落地)
前端·javascript·面试
珑墨27 分钟前
【迭代器】js 迭代器与可迭代对象终极详解
前端·javascript·vue.js
Fantastic_sj35 分钟前
[代码例题] var 和 let 在循环中的作用域差异,以及闭包和事件循环的影响
开发语言·前端·javascript
HashTang1 小时前
【AI 编程实战】第 3 篇:后端小白也能写 API:AI 带我 1 小时搭完 Next.js 服务
前端·后端·ai编程
三年三月1 小时前
React 中 CSS Modules 详解
前端·css
JANG10241 小时前
【Linux】常用指令
linux·服务器·javascript
粉末的沉淀1 小时前
tauri:关闭窗口后最小化到托盘
前端·javascript·vue.js