基于Flex的5×5网格交互优化需求:点击后聚焦9个元素
嘿,我来帮你搞定这个5×5 Flex网格的交互升级!针对你提到的需求,我整理了清晰的实现思路和可直接用的代码方案,咱们一步步来:
核心需求梳理
先把要做的效果明确下来:
- 初始是5×5的Flex网格,中间3×3的元素支持点击
- 点击元素后,该元素变红并调整宽高,其余元素适配它的尺寸
- 新增关键交互:点击这个红色中心元素后,只显示它和周围8个元素(共9个),剩下的16个元素直接隐藏
- 切换点击其他中心元素时,视图同步切换成当前点击元素+它的8个邻居,其余元素消失
实现思路拆解
要实现这个效果,核心是搞定「元素索引管理」和「显示状态控制」:
- 给每个元素加唯一索引:把5×5网格的25个元素按从左到右、从上到下的顺序标上0-24的索引,这样能快速算出任意元素的周围邻居位置
- 点击事件处理逻辑:
- 点击中间3×3的元素时,先把它标记为「当前中心」,加上红色背景和宽高样式
- 根据中心元素的索引,计算出它周围8个邻居的索引(中间3×3的元素的邻居肯定都在5×5网格范围内,不用担心越界)
- 显示/隐藏控制:给元素加
.visible和.hidden类,点击后只给中心+邻居加.visible,其余加.hidden,Flex布局会自动适配剩下的元素排列 - Flex布局适配:切换到9元素视图时,调整元素的宽度占比,让它们刚好排成3×3的网格
具体代码实现
HTML结构
给每个网格元素加上data-index属性存索引,中间3×3的元素加clickable类标记可点击:
<div class="grid-container"> <!-- 第0行 --> <div class="grid-item" data-index="0"></div> <div class="grid-item" data-index="1"></div> <div class="grid-item" data-index="2"></div> <div class="grid-item" data-index="3"></div> <div class="grid-item" data-index="4"></div> <!-- 第1行 --> <div class="grid-item" data-index="5"></div> <div class="grid-item clickable" data-index="6"></div> <div class="grid-item clickable" data-index="7"></div> <div class="grid-item clickable" data-index="8"></div> <div class="grid-item" data-index="9"></div> <!-- 第2行 --> <div class="grid-item" data-index="10"></div> <div class="grid-item clickable" data-index="11"></div> <div class="grid-item clickable" data-index="12"></div> <div class="grid-item clickable" data-index="13"></div> <div class="grid-item" data-index="14"></div> <!-- 第3行 --> <div class="grid-item" data-index="15"></div> <div class="grid-item clickable" data-index="16"></div> <div class="grid-item clickable" data-index="17"></div> <div class="grid-item clickable" data-index="18"></div> <div class="grid-item" data-index="19"></div> <!-- 第4行 --> <div class="grid-item" data-index="20"></div> <div class="grid-item" data-index="21"></div> <div class="grid-item" data-index="22"></div> <div class="grid-item" data-index="23"></div> <div class="grid-item" data-index="24"></div> </div>
CSS样式
设置基础Flex布局,加上点击元素的红色样式、显示/隐藏类,还有切换到3×3视图时的适配样式:
.grid-container { display: flex; flex-wrap: wrap; width: 500px; /* 可根据需求调整总宽度 */ gap: 2px; /* 可选,给元素加间距 */ } .grid-item { width: 20%; /* 5×5网格,每个元素占20%宽度 */ height: 100px; border: 1px solid #ddd; transition: all 0.3s ease; } /* 标记可点击元素 */ .grid-item.clickable { cursor: pointer; background-color: #f0f0f0; } /* 点击后的中心元素样式 */ .grid-item.active { background-color: red; width: 30%; height: 120px; } /* 隐藏元素 */ .grid-item.hidden { display: none; } /* 3×3视图时的容器样式 */ .grid-container.expanded { /* 保持总宽度不变,让元素排成3×3 */ } .grid-container.expanded .grid-item.visible { width: calc(100% / 3 - 4px); /* 减去gap的宽度 */ height: 150px; /* 可选,调整高度适配 */ }
JavaScript逻辑
实现点击事件、索引计算、状态控制:
const gridContainer = document.querySelector('.grid-container'); const gridItems = document.querySelectorAll('.grid-item'); const clickableItems = document.querySelectorAll('.grid-item.clickable'); // 计算中心元素的所有邻居索引 function getSurroundingIndexes(centerIndex) { const visibleIndexes = [centerIndex]; const row = Math.floor(centerIndex / 5); // 中心元素所在行 const col = centerIndex % 5; // 中心元素所在列 // 8个方向:左上、上、右上、左、右、左下、下、右下 const directions = [ [-1, -1], [-1, 0], [-1, 1], [0, -1], [0, 1], [1, -1], [1, 0], [1, 1] ]; // 遍历每个方向,计算邻居索引 directions.forEach(([rowOffset, colOffset]) => { const newRow = row + rowOffset; const newCol = col + colOffset; // 确保邻居在5×5网格范围内 if (newRow >= 0 && newRow < 5 && newCol >= 0 && newCol < 5) { const neighborIndex = newRow * 5 + newCol; visibleIndexes.push(neighborIndex); } }); return visibleIndexes; } // 重置所有元素的状态 function resetGridState() { gridItems.forEach(item => { item.classList.remove('active', 'visible', 'hidden'); }); gridContainer.classList.remove('expanded'); } // 绑定点击事件 clickableItems.forEach(item => { item.addEventListener('click', () => { // 先重置之前的状态 resetGridState(); // 获取当前点击元素的索引 const centerIndex = parseInt(item.dataset.index); // 标记为活跃中心元素 item.classList.add('active'); // 获取要显示的元素索引 const visibleIndexes = getSurroundingIndexes(centerIndex); // 设置显示/隐藏状态 gridItems.forEach((gridItem, index) => { if (visibleIndexes.includes(index)) { gridItem.classList.add('visible'); } else { gridItem.classList.add('hidden'); } }); // 切换到3×3视图的布局 gridContainer.classList.add('expanded'); }); });
关键细节说明
- 索引计算:通过行和列的偏移量快速找到邻居,逻辑简单且不容易出错,哪怕以后网格大小变了,只需要改行数的数值就行
- 状态重置:每次点击新元素前都重置所有状态,避免之前的样式残留导致混乱
- Flex适配:通过给容器加
.expanded类,动态调整元素宽度,让9个元素刚好排成3×3,完美适配视图切换
内容的提问来源于stack exchange,提问作者pawell67
相关产品推荐
相关产品推荐

