目的
蜘蛛纸牌中要实现牌组的连接,就需要吸附功能。从效果图中可以看出我们把一张牌拖到另一张卡牌上的时候,它会自动吸附过去并且左对齐。
效果
代码
<!DOCTYPE html>
<html><head><style>body {display: flex;justify-content: center;align-items: center;height: 100vh;background-color: #2b2b2b;position: relative;//这很关键,如果没有这个左对齐不了margin: 0;}.card {/*设置卡牌的外观*/width: 150px;height: 200px;background-color: #00ffcc;border-radius: 10px;/*为卡牌中间的图案设置格式*/font-size: 100px;font-weight: bold;display: flex;justify-content: center;align-items: center;/*方便左上角和右下角的数字定位*/position: absolute;/*避免选择到文本*/user-select: none;border: 1px solid black;}/*设置卡牌两个对角的数字格式*/.pos-TL {position: absolute;font-size: 20px;top: 5px;left: 5px;}.pos-BR {position: absolute;font-size: 20px;bottom: 5px;right: 5px;transform: rotateZ(180deg);}</style>
</head><body><!--把卡牌里的元素都放到卡牌这个容器里,对卡牌的动画会传到卡牌元素里--><div class="card" id="card1">♠️<div class="card-num pos-TL">6</div><div class="card-num pos-BR">6</div></div><div class="card" id="card2">♠️<div class="card-num pos-TL">3</div><div class="card-num pos-BR">3</div></div><script>let offsetX, offsetY, isDragging = false;const card2 = document.getElementById("card2");const card1 = document.getElementById("card1");card2.addEventListener("mousedown", (e) => {isDragging = true;offsetX = e.clientX - card2.getBoundingClientRect().left;offsetY = e.clientY - card2.getBoundingClientRect().top;})document.addEventListener("mousemove", (e) => {if (isDragging) {card2.style.left = `${e.clientX - offsetX}px`;card2.style.top = `${e.clientY - offsetY}px`;}})document.addEventListener("mouseup", () => {isDragging = false;absorbing()})//吸附函数function absorbing( ) {const firstCard = card1.getBoundingClientRect();const lastCard = card2.getBoundingClientRect();//判断是否大面积重合if (firstCard.right > lastCard.left && firstCard.left < lastCard.right && firstCard.bottom > lastCard.top && firstCard.top < firstCard.bottom) {card2.style.left = `${firstCard.left}px`;}}</script>
</body></html>
总结
- 先说最重要的就是左对齐,如果你没有在
body
里面设置margin:0;
,那么可能出现这样的情况
无论怎么样对无法让两张卡片左对齐,这就是margin
带来的影响,我们需要将其设为0。 - 判断两个元素重叠用
.style.left
还是用.getBoundingClientrect().left
选择.getBoundingClientrect().left
因为后者是基于窗口的位置来计算的,而前者是基于父元素的相对位置计算的。所以前者更加准确,而后者会根据父元素的变化导致预期外的变化。 - 不能修改DOMrect的属性,因为只读。