使用jQuery UI Sortable编程设置每个棋子的对应位置
解决jQuery UI Sortable网格棋子编程式定位问题
要实现页面刷新后保留棋子位置、多用户同步看到位置的需求,核心是从数据库读取每个棋子的坐标,然后在网格渲染完成后将棋子放到对应单元格。以下是修改后的完整实现:
关键修改说明
- 角色数据扩展:从数据库拉取角色时需包含
coords字段(格式如"0,1",空值表示角色在待选区) - 定位函数:新增
setCharacterPositions,根据坐标计算目标单元格并移动棋子 - 初始化时机:页面加载完成后自动执行位置初始化
- 多用户同步:新增可选的
refreshCharacterPositions,用于拉取最新位置实现同步(可配合轮询或WebSocket)
修改后的代码
JavaScript
let gridSize = 7, // 实际场景从数据库获取,包含coords字段 characters = [ {"id" : "1" , "name" : "测试角色", "hp" : "112", "coords": "2,3"} ]; // 生成网格 $('.grid') .css(`grid-template-columns`, `repeat(${gridSize}, 4rem)`) .html([...Array(gridSize**2)].map(() => '<div class="cell"></div>').join('')); // 渲染角色容器 const $charactersContainer = $('.characters') .html(characters.map(character => `<div class="character" data-character-id="${character.id}"> <div class="stats" id='${character.id}'> <p>${character.name}</p> <p>hp: ${character.hp}</p> </div> </div>`).join('')); // 初始化Sortable $charactersContainer.add('.grid .cell').sortable({ connectWith: '.characters, .grid .cell', cursor: 'grabbing', receive: (e, ui) => { if(ui.item.parent().hasClass('cell')) { const $cell = $(e.target); const coords = [ $cell.index() % gridSize, Math.floor($cell.index() / gridSize) ].toString(); const characterId = ui.item.find('.stats').attr('id'); updateCharacterPosition(characterId, coords); } } }); // 编程式设置角色位置 function setCharacterPositions() { characters.forEach(character => { if (!character.coords) return; const [x, y] = character.coords.split(',').map(Number); const cellIndex = y * gridSize + x; const $targetCell = $('.grid .cell').eq(cellIndex); const $character = $(`.character[data-character-id="${character.id}"]`); $targetCell.append($character); }); } // 页面加载后初始化位置 $(document).ready(setCharacterPositions); // 更新角色位置到数据库 function updateCharacterPosition(characterId, coords) { $.ajax({ url: "/coords/" + characterId, method: 'PATCH', data: { _token: $('meta[name="csrf-token"]').attr('content'), newcoords: coords }, success: () => { console.log('角色位置更新成功'); // 可选:触发全局刷新同步给其他用户 // refreshCharacterPositions(); }, error: (xhr, status, error) => { console.error('位置更新失败:', error); } }); } // 可选:拉取所有角色最新位置(用于多用户同步) function refreshCharacterPositions() { $.get('/coords/all', data => { characters = data; $charactersContainer.html(characters.map(character => `<div class="character" data-character-id="${character.id}"> <div class="stats" id='${character.id}'> <p>${character.name}</p> <p>hp: ${character.hp}</p> </div> </div>`).join('')); setCharacterPositions(); }); }
CSS
.grid{ border: 2px solid gray; display: grid; width: fit-content; } .grid .cell{ align-items: center; aspect-ratio: 1 / 1; border: 1px solid lightgray; display: flex; justify-content: center; overflow: visible; } .grid .cell:has(.character):hover{ border-width: 2px; box-sizing: border-box; } .characters{ border: 2px solid gray; display: flex; gap: 1rem; margin-top: 1rem; min-height: 3rem; min-width: 6rem; padding: 1rem; width: fit-content; } .character{ align-items: end; background-color: #000000; border-radius: 50%; color: #ffffff; display: flex; height: 3rem; justify-content: center; text-align: center; width: 3rem; cursor: grab; } .character .stats{ background-color: inherit; padding: 4px; } .character p{ font-size: .66rem; margin: 0; white-space: nowrap; }
HTML
<div class="grid"></div> <div class="characters"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script> <meta name="csrf-token" content="{{ csrf_token() }}">
后端配合要点
- 角色数据接口:GET
/coords/all返回包含id、name、hp、coords的角色列表 - 更新接口:PATCH
/coords/{id}接收newcoords参数并更新数据库 - 实时同步优化:如果需要低延迟的多用户同步,推荐用Laravel Echo + WebSocket(如Pusher),当位置更新时推送给所有在线用户,触发
refreshCharacterPositions
内容的提问来源于stack exchange,提问作者Scarlet D.
相关产品推荐
相关产品推荐

