拖拉拽效果加点击事件

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 小时前
PDF离线工具箱深度解析:4MB纯前端单文件,40+功能全本地运行,文件绝不上传
前端·pdf·1024程序员节
小poop7 小时前
CSS 基础与实战:从入门到精通网页美化
前端
Csvn9 小时前
运行时性能
前端
Never_every9910 小时前
位图转矢量工具哪个好?实测抠抠图AI位图转矢量工具
大数据·前端
paopaokaka_luck10 小时前
宠物门店经营管理系统(销售与库存联动、进货自动记账、 退换与退款关联、员工个人业绩、ECharts 经营分析、滞销识别与客户分层、宠物档案年龄计算)
前端·javascript·spring boot·mysql·echarts·mybatis·1024程序员节
空中湖11 小时前
用 React 写数据大屏:为什么我不建议用图表库
前端·react.js·前端框架
狮子座的男孩12 小时前
html+css基础:25、3D变换(3D空间与景深/透视点的位置/位移/旋转/缩放/多重变换/背部可见性)
css·经验分享·html·旋转·透视点·缩放/位移·3d变换/空间与景深
欣欣之王来了12 小时前
原始HTML插值:v-html指令的使用与安全风险
前端·学习·架构·项目·vue3教程
IT_陈寒12 小时前
Redis的LRU淘汰策略坑了我一整天
前端·人工智能·后端
计算机魔术师12 小时前
砍半价格、参数再涨,国产旗舰追到 Opus 鼻尖了
前端