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

基于原生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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 08:32:16