js实现宫格布局图片放大交互动画

可直接运行代码

html 复制代码
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>五图交互布局</title>
  <style>
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }

    .gallery {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      grid-template-rows: repeat(2, 1fr);
      gap: 6px;
      width: 400px;
      margin: 40px auto;
    }

    .item {
      background-color: #eee;
      border: 2px solid #333;
      background-size: cover;
      background-position: center;
      cursor: pointer;
      transition: all 0.3s ease;
      color: red;
      aspect-ratio: 1 / 1;
    }

    /* 默认布局 1 - p1大图 */

    .gallery #p1 {
      grid-row: 1 / span 2;
      grid-column: 1;
    }

    .gallery #p2 {
      grid-row: 1;
      grid-column: 2;
    }

    .gallery #p3 {
      grid-row: 1;
      grid-column: 3;
    }

    .gallery #p4 {
      grid-row: 2;
      grid-column: 2;
    }

    .gallery #p5 {
      grid-row: 2;
      grid-column: 3;
    }
  </style>
</head>

<body>
  <div class="gallery">
    <div class="item" id="p1" style="background-image: url('https://picsum.photos/seed/01/400/400')">1</div>
    <div class="item" id="p2" style="background-image: url('https://picsum.photos/seed/02/400/400')">2</div>
    <div class="item" id="p3" style="background-image: url('https://picsum.photos/seed/03/400/400')">3</div>
    <div class="item" id="p4" style="background-image: url('https://picsum.photos/seed/04/400/400')">4</div>
    <div class="item" id="p5" style="background-image: url('https://picsum.photos/seed/05/400/400')">5</div>
  </div>

  <script>
    // 当前放大图片的下标
    let oldindex = 0
    // 当前放大图片的列
    let oldcolumn = 1
    let list = [
      [1, '1 / span 2'],
      [2, 1],
      [3, 1],
      [2, 2],
      [3, 2],
    ]
    document.querySelector('.gallery').addEventListener('mouseover', (e) => {
      if (!e.target.classList.contains('item')) return;
      let p1 = document.getElementById('p1');
      let p2 = document.getElementById('p2');
      let p3 = document.getElementById('p3');
      let p4 = document.getElementById('p4');
      let p5 = document.getElementById('p5');
      // 当前点击图片的位置
      const clickedItemStyle = window.getComputedStyle(e.target);
      let x = clickedItemStyle.getPropertyValue('grid-column-start')
      let y = clickedItemStyle.getPropertyValue('grid-row-start')
      // console.log(x, y);
      if (x == oldcolumn) return;
      let newindex = 0
      let newcolumn = x
      list.forEach((item, i) => {
        // 如果垮了中间图片就修改影响的中间图片位置
        if (Math.abs(newcolumn - oldcolumn) > 1 && item[0] == 2 && item[1] != y) {
          // console.log('需要位移的中间图片的下标', i)
          if (oldcolumn < x) {
            list[i] = [list[i][0] - 1, item[1]]
          } else {
            list[i] = [list[i][0] + 1, item[1]]
          }
        }
        if (x == item[0] && y == item[1]) {
          // console.log('放大图片下标', i)
          // 放大当前点击图片
          list[i] = [item[0], '1 / span 2']
          // console.log('缩小放大图片', oldindex)
          // 缩小放大的图片,当前点击的第几排就向第几排缩小
          list[oldindex] = [list[oldindex][0], y]
          // 存储当前放大图片下标
          newindex = i
        }
        // 缩小放大列的另一个图片
        if (item[0] == x && item[1] != y) {
          // console.log("缩小图片下标", i)
          // 根据上一次放大图片的列,向上次放大列位移,当前大于上一次减一,小于上一次加一
          if (oldcolumn < x) {
            list[i] = [list[i][0] - 1, item[1]]
          } else {
            list[i] = [list[i][0] + 1, item[1]]
          }
        }
      })
      // console.log(list)
      // 赋值当前放大图片下标和列
      oldindex = newindex
      oldcolumn = newcolumn
      // 重定义布局
      p1.style.gridColumn = list[0][0];
      p1.style.gridRow = list[0][1];
      p2.style.gridColumn = list[1][0];
      p2.style.gridRow = list[1][1];
      p3.style.gridColumn = list[2][0];
      p3.style.gridRow = list[2][1];
      p4.style.gridColumn = list[3][0];
      p4.style.gridRow = list[3][1];
      p5.style.gridColumn = list[4][0];
      p5.style.gridRow = list[4][1];
    });
  </script>

</body>

</html>
相关推荐
大家的林语冰5 小时前
ES5 凉凉,Babel 8 正式发布,默认不再编译为 ES5 和 CJS......
前端·javascript·前端工程化
weedsfly7 小时前
异步编程全景与事件循环——彻底搞懂 JS 执行机制
前端·javascript
用户1733598075377 小时前
纯前端 PDF 数字签名实战:Vue 3 + pdf-lib 在浏览器里完成签名嵌入
前端·javascript
JieE21218 小时前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE21218 小时前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
kyriewen1 天前
我用 AI 一周写完了整个项目,上线第一天就崩了——这是我踩过最贵的 5 个坑
前端·javascript·ai编程
Larcher1 天前
AI Loop:让AI像人一样自主完成任务的核心机制
javascript·人工智能·设计模式
默_笙1 天前
🃏 JS 只有 8 种数据类型,但我花了 2 天才搞懂 null 和 undefined 的区别
javascript
jump_jump1 天前
流式 HTML:从 htmx 片段装配到浏览器原生增量渲染
javascript·性能优化·前端工程化
swipe1 天前
正则表达式入门到进阶:从表单校验到手写模板引擎
前端·javascript·面试