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

基于jQuery UI的战舰网格拖拽功能优化技术问询

战舰游戏拖拽网格功能解决方案

分步问题解决

1. 限制船只仅可放置在grid-square内,禁止指针区域放置

当前代码的containment: grid会将指针区域也纳入拖拽范围,需调整为仅允许在网格方块上放置,无效区域释放时自动回退。

修改拖拽与放置配置:

$(ships).draggable({
  start: function(event, ui) {
    // 记录初始位置用于回退
    $(this).data('originalPosition', $(this).position());
  },
  stop: function(event, ui) {
    // 未放置到有效区域则返回初始位置
    if (!$(this).data('dropped')) {
      $(this).animate($(this).data('originalPosition'), 200);
    }
    $(this).removeData('dropped');
  }
});

// 仅给网格方块绑定放置事件
$(squares).droppable({
  accept: '.ship',
  drop: function(event, ui) {
    ui.draggable.data('dropped', true);
  }
});

2. 允许拖拽穿过空白区域但不能放置,拖拽开始不立即进入网格

移除containment: grid后,船只可自由拖拽穿过列表与网格间的空白区域,只有grid-square是有效放置目标,空白区域释放时会触发回退逻辑,自然满足需求。

3. 拖拽结束自动对齐到最近网格方块

通过计算网格方块的尺寸,将船只位置对齐到网格坐标,禁止放置在方块间隙:

// 获取网格方块的统一尺寸
let squareSize = $('.grid-square').outerWidth();

$(ships).draggable({
  // ... 保留之前的start/stop基础逻辑
  stop: function(event, ui) {
    let ship = $(this);
    if (!ship.data('dropped')) {
      ship.animate(ship.data('originalPosition'), 200);
      return;
    }

    // 计算相对于网格的坐标
    let gridOffset = $('#setupgrid').offset();
    let shipOffset = ship.offset();
    let relativeX = shipOffset.left - gridOffset.left;
    let relativeY = shipOffset.top - gridOffset.top;

    // 对齐到最近的网格方块左上角
    let alignedX = Math.round(relativeX / squareSize) * squareSize;
    let alignedY = Math.round(relativeY / squareSize) * squareSize;

    // 确保船只不超出网格边界
    let gridWidth = $('#setupgrid').width();
    let gridHeight = $('#setupgrid').height();
    let shipWidth = ship.outerWidth();
    let shipHeight = ship.outerHeight();

    if (alignedX + shipWidth > gridWidth) alignedX = gridWidth - shipWidth;
    if (alignedY + shipHeight > gridHeight) alignedY = gridHeight - shipHeight;
    if (alignedX < 0) alignedX = 0;
    if (alignedY < 0) alignedY = 0;

    // 应用对齐后的位置
    ship.offset({
      left: gridOffset.left + alignedX,
      top: gridOffset.top + alignedY
    });
  }
});

完整修改后的JavaScript代码

$(function() {
  let ships = document.getElementsByClassName('ship');
  let squares = document.getElementsByClassName('grid-square');
  let squareSize = $('.grid-square').outerWidth();

  $(ships).draggable({
    start: function(event, ui) {
      $(this).data('originalPosition', $(this).position());
      $(this).data('dropped', false);
    },
    stop: function(event, ui) {
      let ship = $(this);
      if (!ship.data('dropped')) {
        ship.animate(ship.data('originalPosition'), 200);
        return;
      }

      let gridOffset = $('#setupgrid').offset();
      let shipOffset = ship.offset();
      let relativeX = shipOffset.left - gridOffset.left;
      let relativeY = shipOffset.top - gridOffset.top;

      let alignedX = Math.round(relativeX / squareSize) * squareSize;
      let alignedY = Math.round(relativeY / squareSize) * squareSize;

      let gridWidth = $('#setupgrid').width();
      let gridHeight = $('#setupgrid').height();
      let shipWidth = ship.outerWidth();
      let shipHeight = ship.outerHeight();

      if (alignedX + shipWidth > gridWidth) alignedX = gridWidth - shipWidth;
      if (alignedY + shipHeight > gridHeight) alignedY = gridHeight - shipHeight;
      if (alignedX < 0) alignedX = 0;
      if (alignedY < 0) alignedY = 0;

      ship.offset({
        left: gridOffset.left + alignedX,
        top: gridOffset.top + alignedY
      });
    }
  });

  $(squares).droppable({
    accept: '.ship',
    drop: function(event, ui) {
      ui.draggable.data('dropped', true);
    }
  });
});

额外优化方向

  • 添加拖拽时半透明效果:在draggable配置中加入opacity: 0.7
  • 禁止船只重叠:放置前检查目标网格区域是否已被占用,若占用则触发回退
  • 支持船只旋转:添加切换按钮,动态调整船只尺寸与对齐逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 02:15:35