拖拉拽效果加点击事件

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>
相关推荐
xixingzhe28 分钟前
Nginx 配置多个监听端口
服务器·前端·nginx
程序员Bears25 分钟前
从零打造个人博客静态页面与TodoList应用:前端开发实战指南
java·javascript·css·html5
清风细雨_林木木1 小时前
Vue 2 项目中配置 Tailwind CSS 和 Font Awesome 的最佳实践
前端·css·vue.js
逊嘘1 小时前
【Web前端开发】CSS基础
前端·css
小宁爱Python1 小时前
深入掌握CSS Flex布局:从原理到实战
前端·javascript·css
Attacking-Coder1 小时前
前端面试宝典---webpack面试题
前端·面试·webpack
极小狐2 小时前
极狐GitLab 容器镜像仓库功能介绍
java·前端·数据库·npm·gitlab
程序猿阿伟2 小时前
《Flutter社交应用暗黑奥秘:模式适配与色彩的艺术》
前端·flutter
rafael(一只小鱼)2 小时前
黑马点评实战笔记
前端·firefox
weifont2 小时前
React中的useSyncExternalStore使用
前端·javascript·react.js