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>