<!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>