React 两行图片列表如何实现方向键直观导航功能
两行flex布局垂直导航实现方案
核心逻辑
你只需要先确定两个基础变量即可实现通用逻辑,不受列表长度变化影响:
- 单行可容纳元素数量
perRow:如果是固定宽度元素,用容器宽度除以单个元素的总宽度(含外边距、内边距)取整即可;如果是固定每行显示数量直接赋值即可,窗口大小变化时可以重新计算适配响应式布局。 - 当前激活元素的索引
currentActiveIndex:注意统一索引起始规则,以下示例以0作为索引起始值。
垂直导航跳转规则:
- 按下向下方向键:目标索引 =
currentActiveIndex + perRow,如果目标索引小于列表总长度,直接激活对应元素;如果目标索引超出总长度,可根据交互需求选择不跳转,或者激活第二行最后一个元素。 - 按下向上方向键:目标索引 =
currentActiveIndex - perRow,如果目标索引大于等于0,直接激活对应元素;如果目标索引小于0,可选择不跳转,或者激活第一行第一个元素。
你提到的从第3个区块跳转到第8个区块的场景,刚好符合单行数量为5的逻辑:3+5=8(如果索引从1开始计数)。
代码示例
// 提前获取DOM元素 const imgItems = document.querySelectorAll('.img-item') const container = document.querySelector('.img-container') // 单个元素总宽度,包含你设置的左右margin、padding,按需调整 const singleItemTotalWidth = imgItems[0].offsetWidth + 16 let currentActiveIndex = 0 // 初始激活第一个元素 let perRow = 0 // 计算单行可容纳数量,可在window.resize事件中重新调用适配响应式 function calcPerRow() { perRow = Math.floor(container.offsetWidth / singleItemTotalWidth) } calcPerRow() // 方向键监听 document.addEventListener('keydown', (e) => { let targetIndex = currentActiveIndex switch(e.key) { // 原有左右导航逻辑可直接保留 case 'ArrowLeft': targetIndex = Math.max(0, currentActiveIndex - 1) break case 'ArrowRight': targetIndex = Math.min(imgItems.length - 1, currentActiveIndex + 1) break // 上下导航逻辑 case 'ArrowDown': targetIndex = currentActiveIndex + perRow // 超出列表长度时自动调整为最后一个元素,不需要该逻辑可删除此行,直接判断targetIndex >= imgItems.length则不跳转 targetIndex = Math.min(imgItems.length - 1, targetIndex) break case 'ArrowUp': targetIndex = currentActiveIndex - perRow // 索引小于0时自动调整为第一个元素,不需要该逻辑可删除此行,直接判断targetIndex < 0则不跳转 targetIndex = Math.max(0, targetIndex) break default: return } // 更新激活状态 if (targetIndex !== currentActiveIndex) { imgItems[currentActiveIndex].classList.remove('active') currentActiveIndex = targetIndex imgItems[currentActiveIndex].classList.add('active') // 如果需要滚动到可视区域可自行加scrollIntoView逻辑 } })
非偶数长度适配
如果列表总长度不是偶数,第二行元素数量少于第一行,上述代码已经做了边界兼容,不需要额外调整;如果不需要自动适配到首尾元素,只要在跳转前加边界判断,不符合条件就不执行激活逻辑即可。
内容的提问来源于stack exchange,提问作者LukeVenter
相关产品推荐
相关产品推荐

