You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

卡片Hover动画水平移动时闪烁重置问题求助

问题解决:卡组卡片Hover闪烁问题

问题描述

实现卡组动画时,顶部卡片hover通过translateY(-20px)向上位移,但鼠标在卡片底部区域水平移动时,卡片会出现闪烁——动画重置为原始状态后又恢复hover状态。且增大translate偏移量,闪烁触发区域会扩大。尝试调整translate、position、top、transition属性均无效。

原因分析

hover事件绑定在卡片本身,当卡片向上位移后,鼠标原本处于的卡片底部区域会脱离卡片的实际范围,导致hover状态被取消;卡片回到原位后,鼠标又重新触发hover,如此循环造成闪烁。

解决方案

方案1:将hover事件绑定到父容器

把hover触发逻辑转移到卡组容器#deck上,只要鼠标在容器范围内,就控制顶部卡片位移,避免卡片位移后脱离hover范围:

修改CSS部分:

#deck {
  display: flex;
  justify-content: space-around;
  position: relative;
  /* 给容器设置合适高度,覆盖卡片位移前后的范围 */
  height: 120px;
}

.card {
  height: 100px;
  width: 100px;
  background-color: red;
  position: absolute;
  border: 1px solid black;
}

#deck .card:last-child {
  transition: transform 0.3s ease;
}

/* 父容器hover时控制顶部卡片位移 */
#deck:hover .card:last-child {
  transform: translateY(-20px);
}

方案2:用伪元素扩展hover区域

给顶部卡片添加透明伪元素,覆盖卡片位移前的底部区域,确保鼠标移动时始终处于hover触发范围内:

修改CSS部分:

#deck .card:last-child {
  transition: transform 0.3s ease;
  position: relative; /* 伪元素需要相对定位 */
}

#deck .card:last-child::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: -20px; /* 偏移量与translateY一致 */
  z-index: -1; /* 不干扰卡片本身的交互 */
}

代码优化建议

JavaScript优化

  1. 封装全局变量,避免污染全局作用域:
// 用IIFE封装代码
(function() {
  const game = document.getElementById('game');
  const deckEl = document.getElementById('deck');
  const hand = document.getElementById('hand');
  
  let arr = [{card: 1, text:"Attack"},{card: 2, text:"Attack"},{card: 3, text:"Attack"},{card: 4, text:"Shield"},{card: 5, text:"Shield"},{card: 6, text:"Shield"},{card: 7, text:"Parry"},{card: 8, text:"Parry"},{card: 9, text:"Parry"}];
  let cardsInHand = [];

  // 标准Fisher-Yates洗牌算法,纯函数不修改原数组
  function shuffleDeck(array) {
    const newArr = [...array];
    let i = newArr.length;
    while(i--) {
      const i2 = Math.floor(Math.random() * (i + 1)); // 修正原算法最后一个元素不参与洗牌的问题
      [newArr[i], newArr[i2]] = [newArr[i2], newArr[i]];
    }
    return newArr;
  }

  function drawCards(cardAmount) {
    // 添加边界判断,避免数组为空时报错
    if (arr.length === 0) return;
    const drawCount = Math.min(cardAmount, arr.length);
    for(let i = 0; i < drawCount; i++) {
      cardsInHand.push(arr.pop());
    }
  }

  function generateDeck() {
    let cardOutline = 200;
    arr.forEach((card, index) => {
      const cardEl = document.createElement('div');
      cardEl.classList.add('card');
      cardOutline -= 3;
      cardEl.style.top = `${cardOutline}px`;
      // 显式设置z-index,确保卡片堆叠顺序正确
      cardEl.style.zIndex = index;
      deckEl.appendChild(cardEl);
    });
  }

  arr = shuffleDeck(arr); // 使用纯函数洗牌后重新赋值
  generateDeck();     
  drawCards(3);
})();

CSS优化

  1. 使用CSS变量统一管理参数,便于维护:
:root {
  --card-width: 100px;
  --card-height: 100px;
  --hover-offset: 20px;
  --card-gap: 3px;
}

#deck {
  display: flex;
  justify-content: space-around;
  position: relative;
  height: calc(var(--card-height) + var(--hover-offset));
}

.card {
  height: var(--card-height);
  width: var(--card-width);
  background-color: red;
  position: absolute;
  border: 1px solid black;
}

#deck .card:last-child {
  transition: transform 0.3s ease;
}

#deck:hover .card:last-child {
  transform: translateY(calc(-1 * var(--hover-offset)));
}

内容的提问来源于stack exchange,提问作者l00duck

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 16:17:22