Bootstrap

Html笔记()蜘蛛纸牌之卡牌吸附

目的

蜘蛛纸牌中要实现牌组的连接,就需要吸附功能。从效果图中可以看出我们把一张牌拖到另一张卡牌上的时候,它会自动吸附过去并且左对齐。

效果

在这里插入图片描述

代码

<!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的属性,因为只读。
;