基于原生JS实现移动端可拖拽元素:糖果消消乐适配求助
适配移动端的糖果消消乐拖拽改造方案
核心思路
直接替换桌面端的Draggable实现,完全基于移动端touch事件(touchstart/touchmove/touchend)实现拖拽逻辑,完全保留你原有的匹配消除、得分、糖果生成等游戏核心逻辑,只改动拖拽触发的部分。
代码改造步骤
假设你的原有代码中,糖果元素类为.candy,游戏网格是固定行列布局,以下是关键改造点:
1. 移除Draggable相关代码
删掉所有带draggable="true"的属性,以及ondragstart/ondragover/ondrop这类拖拽事件的监听和处理函数。
2. 绑定Touch事件
给每个糖果元素绑定三个核心触摸事件:
const candies = document.querySelectorAll('.candy'); candies.forEach(candy => { candy.addEventListener('touchstart', handleTouchStart); candy.addEventListener('touchmove', handleTouchMove); candy.addEventListener('touchend', handleTouchEnd); });
3. 实现Touch事件处理函数
(1)记录拖拽初始状态(touchstart)
保存选中糖果的信息、触摸初始位置,以及该糖果在网格中的行列坐标:
let selectedCandy = null; let startX = 0; let startY = 0; let startGridX = 0; let startGridY = 0; // 替换成你实际的网格行列数 const gridCols = 8; const gridRows = 8; function handleTouchStart(e) { e.preventDefault(); // 阻止页面滚动/缩放干扰 selectedCandy = e.target; const touch = e.touches[0]; startX = touch.clientX; startY = touch.clientY; // 从元素的dataset获取网格坐标(假设你原有代码里用data-grid-x/data-grid-y存行列) startGridX = parseInt(selectedCandy.dataset.gridX); startGridY = parseInt(selectedCandy.dataset.gridY); }
(2)实时跟随触摸移动(touchmove)
让选中的糖果视觉上跟随触摸点移动:
function handleTouchMove(e) { if (!selectedCandy) return; e.preventDefault(); const touch = e.touches[0]; const deltaX = touch.clientX - startX; const deltaY = touch.clientY - startY; // 用transform实现拖拽位移(需确保糖果元素是position: relative/absolute) selectedCandy.style.transform = `translate(${deltaX}px, ${deltaY}px)`; }
(3)结束拖拽并触发游戏逻辑(touchend)
判断拖拽方向,找到目标交换糖果,然后调用你原有的游戏逻辑:
function handleTouchEnd(e) { if (!selectedCandy) return; e.preventDefault(); const touch = e.changedTouches[0]; const endX = touch.clientX; const endY = touch.clientY; const deltaX = endX - startX; const deltaY = endY - startY; let targetGridX = startGridX; let targetGridY = startGridY; // 判断拖拽方向(仅处理相邻格子交换,符合消消乐规则) if (Math.abs(deltaX) > Math.abs(deltaY)) { // 左右拖拽 targetGridX += deltaX > 0 ? 1 : -1; } else { // 上下拖拽 targetGridY += deltaY > 0 ? 1 : -1; } // 校验目标格子是否在网格范围内 if (targetGridX >= 0 && targetGridX < gridCols && targetGridY >= 0 && targetGridY < gridRows) { const targetCandy = document.querySelector(`.candy[data-grid-x="${targetGridX}"][data-grid-y="${targetGridY}"]`); if (targetCandy) { // 调用你原有代码中的交换糖果函数 swapCandies(selectedCandy, targetCandy); // 调用你原有代码中的匹配消除、得分计算逻辑 checkMatchesAndScore(); } } // 重置选中状态和样式 selectedCandy.style.transform = ''; selectedCandy = null; }
4. 移动端样式适配
确保游戏在手机上显示正常:
- 给游戏网格设置
width: 100vw; max-width: 480px; margin: 0 auto,限制最大宽度同时占满屏幕 - 糖果元素用
width: calc(100% / ${gridCols})设置自适应大小 - 给
body添加touch-action: none,彻底禁用移动端默认触摸行为
关键注意点
- 所有touch事件必须调用
e.preventDefault(),避免页面滚动、缩放干扰拖拽 - 只处理相邻格子的交换,不要允许跨多格拖拽,保持消消乐常规规则
- 原有的匹配消除、糖果下落、得分统计等逻辑完全保留,无需修改
内容的提问来源于stack exchange,提问作者Bia Souza
相关产品推荐
相关产品推荐

