如何实现英雄图片可拖拽放置到等级图片对应区域的功能
实现思路
- 核心用原生HTML5 Drag & Drop API实现,不需要引入额外第三方库,代码量少易维护
- 先调整等级区域结构:给每个等级图片套独立父容器,父容器内新增专门用来放置英雄的区域,避免拖拽放置时打乱原有等级图布局
- 绑定三类核心拖拽事件即可完成基础功能:
dragstart:英雄图片开始拖拽时,存储当前拖拽英雄的图片信息dragover:等级放置区域监听该事件并阻止默认行为,允许元素被放置到当前区域drop:松开鼠标放置时,读取之前存储的英雄信息,将英雄图片插入到当前放置区域
代码示例
1. 调整后的HTML(仅修改.place部分,其他.champs部分保持你原有代码不变)
<div class="place"> <!-- 每个等级包成独立容器 --> <div class="rank-item"> <img src="images/S.jpg" alt="S"> <div class="champ-container"></div> <!-- 专门放拖拽进来的英雄 --> </div> <div class="rank-item"> <img src="images/A.jpg" alt="A"> <div class="champ-container"></div> </div> <div class="rank-item"> <img src="images/B.jpg" alt="B"> <div class="champ-container"></div> </div> <div class="rank-item"> <img src="images/C.jpg" alt="C"> <div class="champ-container"></div> </div> <div class="rank-item"> <img src="images/D.jpg" alt="D"> <div class="champ-container"></div> </div> <div class="rank-item"> <img src="images/E.jpg" alt="E"> <div class="champ-container"></div> </div> <div class="rank-item"> <img src="images/F.jpg" alt="F"> <div class="champ-container"></div> </div> <div class="rank-item"> <img src="images/Troll.jpg" alt="Troll"> <div class="champ-container"></div> </div> </div>
2. 基础排版CSS(可根据自己的页面风格调整)
.rank-item { display: inline-flex; flex-direction: column; align-items: center; margin: 0 10px 20px 0; vertical-align: top; } .champ-container { min-width: 100px; min-height: 100px; border: 2px dashed #ccc; margin-top: 8px; padding: 4px; } /* 拖拽到容器上方时高亮 */ .champ-container.drag-over { border-color: #2ecc71; background-color: rgba(46, 204, 113, 0.1); } /* 拖拽中的英雄半透明 */ .champs img.dragging { opacity: 0.5; }
3. JavaScript实现代码(直接复制到你的JS文件中即可)
// 存储当前拖拽的英雄图片信息 let draggedChamp = null; // 给所有英雄图片绑定拖拽开始事件 document.querySelectorAll('.champs img').forEach(champImg => { champImg.addEventListener('dragstart', e => { draggedChamp = { src: champImg.src, alt: champImg.alt }; champImg.classList.add('dragging'); // 存储数据方便事件传递 e.dataTransfer.setData('text/plain', JSON.stringify(draggedChamp)); }); champImg.addEventListener('dragend', () => { champImg.classList.remove('dragging'); draggedChamp = null; }); }); // 给所有等级下的放置容器绑定事件 document.querySelectorAll('.champ-container').forEach(container => { // 拖拽经过容器时阻止默认行为,允许放置 container.addEventListener('dragover', e => { e.preventDefault(); container.classList.add('drag-over'); }); // 拖拽离开容器时移除高亮 container.addEventListener('dragleave', () => { container.classList.remove('drag-over'); }); // 放置英雄 container.addEventListener('drop', e => { e.preventDefault(); container.classList.remove('drag-over'); // 读取拖拽数据 const champData = JSON.parse(e.dataTransfer.getData('text/plain')); // 创建新的英雄图片插入到容器里 const newChampImg = document.createElement('img'); newChampImg.src = champData.src; newChampImg.alt = champData.alt; newChampImg.width = 100; // 可选:允许已经放在等级里的英雄再次被拖拽调整位置 newChampImg.draggable = true; newChampImg.addEventListener('dragstart', e => { draggedChamp = { src: newChampImg.src, alt: newChampImg.alt }; newChampImg.classList.add('dragging'); e.dataTransfer.setData('text/plain', JSON.stringify(draggedChamp)); // 拖拽的时候把原图片删掉,实现移动效果 setTimeout(() => newChampImg.remove(), 0); }); container.appendChild(newChampImg); }); });
功能扩展说明
如果需要更多功能可以自行扩展:
- 限制每个等级区域放置的英雄数量
- 支持拖拽英雄回英雄列表移除
- 添加英雄排序、删除按钮
- 存储当前的tier list配置到本地缓存,刷新页面不丢失
内容的提问来源于stack exchange,提问作者BlindJesus
相关产品推荐
相关产品推荐

