You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

点击卡牌图片添加对应卡牌框至卡组列表的实现方案咨询

点击卡牌图片添加对应卡牌框至卡组列表的实现方案咨询

嘿,你的思路方向是对的,算是不错的起步,但确实有几个地方需要调整,才能实现你想要的功能——比如匹配对应卡牌、跟踪数量,还有后续的动画效果。咱们一步步来梳理改进点:


1. 先解决「点击对应卡牌添加对应卡组项」的核心问题

你现在的代码里,addItem函数用document.querySelector(".card-body")只会选中页面中第一个.card-body元素,所以不管点哪个按钮,都会添加同一张卡牌的框架。另外还有个隐藏问题:你的HTML里有重复的id="box"id="Cat1",这不符合HTML规范(id必须唯一),会导致后续JS选择器出错。

改进方案:

  • 给每个ADD按钮传递对应卡牌的标识(比如名称),让函数知道要添加哪张卡
  • 把卡组列表的容器改成唯一id,移除重复的id属性
  • 修改addItem函数,根据标识匹配对应的卡牌模板

修改后的代码示例:

HTML部分(调整按钮和卡组容器)

<div class="container">
  
  <div class="card-image">
    <img src="https://placehold.co/200x300/blue/white?text=Aeito" alt="Aeito">
    <button onclick="addItem('Aeito')">ADD!</button>
  </div>
  <div class="card-image">
    <img src="https://placehold.co/200x300/orange/white?text=Scipius" alt="Scipius">
    <button onclick="addItem('Scipius')">ADD!</button>
  </div>
  
  <div class="card-frame">
    <!-- 唯一的卡组列表容器 -->
    <div id="deck-list">
      <!-- 模板卡片(可以隐藏,只做克隆用) -->
      <div class="card template" style="display:none;">
        <div class="card-body" data-card="Aeito">
          <h5 class="card-title">Aeito</h5>
          <img src="https://placehold.co/200x300/blue/white?text=Aeito" alt="">
        </div>
      </div>
      <div class="card template" style="display:none;">
        <div class="card-body" data-card="Scipius">
          <h5 class="card-title">Scipius</h5>
          <img src="https://placehold.co/200x300/orange/white?text=Scipius" alt="">
        </div>
      </div>
    </div>
  </div>

</div>

JS部分(匹配对应卡牌并克隆)

function addItem(cardName) {
  // 根据卡牌名称找到对应的模板
  const template = document.querySelector(`.card-body[data-card="${cardName}"]`);
  // 克隆模板元素
  const clone = template.cloneNode(true);
  // 添加到卡组列表
  document.getElementById("deck-list").appendChild(clone);
}

2. 实现「跟踪卡牌数量」的功能

要避免重复添加相同卡牌的框架,而是更新数量,可以用一个对象来记录每张卡的数量,每次点击时判断卡组中是否已有该卡牌:

改进方案:

  • 给卡牌框架添加数量显示元素
  • 用全局对象记录数量,点击时更新数量或添加新卡牌

修改后的代码示例:

HTML模板(添加数量元素)

<div class="card-body" data-card="Aeito">
  <h5 class="card-title">Aeito</h5>
  <span class="card-count">x1</span>
  <img src="https://placehold.co/200x300/blue/white?text=Aeito" alt="">
</div>

JS部分(跟踪并更新数量)

// 初始化卡牌数量记录
const cardQuantity = {
  Aeito: 0,
  Scipius: 0
};

function addItem(cardName) {
  const deckList = document.getElementById("deck-list");
  // 检查卡组中是否已有该卡牌
  const existingCard = deckList.querySelector(`.card-body[data-card="${cardName}"]`);

  if (existingCard) {
    // 已有该卡牌,更新数量
    cardQuantity[cardName]++;
    existingCard.querySelector(".card-count").textContent = `x${cardQuantity[cardName]}`;
  } else {
    // 没有该卡牌,克隆模板并添加
    const template = document.querySelector(`.card-body[data-card="${cardName}"]`);
    const clone = template.cloneNode(true);
    cardQuantity[cardName] = 1;
    deckList.appendChild(clone);
  }
}

3. 用GSAP实现「卡牌移动到卡组」的动画效果

要实现动画,核心思路是创建一个和原卡牌一模一样的“幽灵元素”,用GSAP驱动它从原位置动画到卡组位置,动画结束后再更新卡组:

示例代码:

function addItem(cardName) {
  // 获取原卡牌的位置和元素
  const sourceCard = document.querySelector(`.card-image img[alt="${cardName}"]`);
  // 创建幽灵元素
  const ghostCard = sourceCard.cloneNode(true);
  document.body.appendChild(ghostCard);

  // 设置幽灵元素的初始位置(和原卡牌重叠)
  gsap.set(ghostCard, {
    position: "absolute",
    top: sourceCard.offsetTop,
    left: sourceCard.offsetLeft,
    width: sourceCard.offsetWidth,
    height: sourceCard.offsetHeight,
    zIndex: 9999,
    pointerEvents: "none" // 避免动画过程中干扰点击
  });

  // 获取卡组列表的目标位置
  const deckList = document.getElementById("deck-list");
  const targetRect = deckList.getBoundingClientRect();

  // 执行动画:移动+缩小+淡出
  gsap.to(ghostCard, {
    x: targetRect.left - sourceCard.offsetLeft,
    y: targetRect.top - sourceCard.offsetTop,
    width: 50, // 缩小到卡组卡片的大小
    height: 50,
    opacity: 0,
    duration: 0.6,
    ease: "power2.out",
    onComplete: () => {
      // 动画结束后移除幽灵元素,更新卡组
      ghostCard.remove();
      updateDeck(cardName);
    }
  });
}

// 把之前的数量更新逻辑抽成单独函数
function updateDeck(cardName) {
  const deckList = document.getElementById("deck-list");
  const existingCard = deckList.querySelector(`.card-body[data-card="${cardName}"]`);

  if (existingCard) {
    cardQuantity[cardName]++;
    existingCard.querySelector(".card-count").textContent = `x${cardQuantity[cardName]}`;
  } else {
    const template = document.querySelector(`.card-body[data-card="${cardName}"]`);
    const clone = template.cloneNode(true);
    cardQuantity[cardName] = 1;
    deckList.appendChild(clone);
  }
}

总结

你的初始思路是可行的,只要逐步解决对应卡牌匹配唯一id规范数量跟踪这几个基础问题,再结合GSAP实现动画,就能完成你想要的卡组 builder 功能啦。建议先把基础功能调试通,再添加动画效果,这样更容易排查问题。

备注:内容来源于stack exchange,提问作者artcank

火山引擎 最新活动