原生js实现手风琴效果

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1,minimum-scale=1, user-scalable=no" />
    <title>js手风琴</title>
    <link rel="shortcut icon" href="./img/logo.png" type="image/x-icon" />
    <link rel="stylesheet" href="./css/index.css" />
  </head>

  <body>
    <div id="app">
      <div><img src="./img/image1.jpg" alt="" /></div>
      <div>
        <img src="./img/image2.jpg" alt="" />
        <div class="text">
          <p>some text here</p>
        </div>
      </div>
      <div><img src="./img/image3.jpg" alt="" /></div>
      <div><img src="./img/image4.jpg" alt="" /></div>
      <div><img src="./img/image5.jpg" alt="" /></div>
      <div>
        <img src="./img/image6.jpg" alt="" />
        <div class="text">
          <h1>this is a big title</h1>
          <p>Laborum anim quis non sint qui. Non deserunt laboris nulla proident tempor in occaecat. Excepteur proident ex veniam labore. Magna dolor sunt pariatur nisi nulla. Est pariatur amet cillum sint nostrud. Proident mollit occaecat exercitation minim nisi labore ullamco nulla mollit pariatur. Commodo aute est culpa pariatur velit tempor enim ipsum deserunt id non tempor.</p>
        </div>
      </div>
      <div><img src="./img/image7.jpg" alt="" /></div>
      <div><img src="./img/image8.jpg" alt="" /></div>
      <div><img src="./img/image9.jpg" alt="" /></div>
      <div><img src="./img/image10.jpg" alt="" /></div>
      <div><img src="./img/image11.jpg" alt="" /></div>
      <div><img src="./img/image12.jpg" alt="" /></div>
      <div><img src="./img/image13.jpg" alt="" /></div>
      <div><img src="./img/image14.jpg" alt="" /></div>
      <div><img src="./img/image15.jpg" alt="" /></div>
      <div><img src="./img/image16.jpg" alt="" /></div>
      <div><img src="./img/image17.jpg" alt="" /></div>
      <div><img src="./img/image18.jpg" alt="" /></div>
      <div><img src="./img/image19.jpg" alt="" /></div>
      <div><img src="./img/image20.jpg" alt="" /></div>
    </div>
    <script src="./js/index.js"></script>
    <script>
      let { active } = new Gellary('app', { width: 5, height: 4 })
    </script>
  </body>
</html>

 

css部分

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
#app {
  overflow: hidden;
  width: 500px;
}

/* 使用浮动实现对元素的布局 */
.gellary > div {
  float: left;
  width: 100px;
  height: 100px;
  overflow: hidden;
  border-right: 1px solid #ddd;
  border-bottom: 1px solid #ddd;
  position: relative;
  transition: all 0.3s;
}
.gellary > div:hover {
  cursor: pointer;
}

/* 设置div中的图片垂直水平居中 */
#app > div > img {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* 设置div中的文本隐藏状态 */
#app > div > .text {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 340px;
  transform: translateY(100%);
  z-index: 1;
  background-color: rgba(255, 255, 255, 0.8);
  opacity: 0;
  transition: all 0.3s;
}

/* 激活状态的文本的样式 */
#app > div.active > .text {
  /* 从隐藏的状态,转换为显示状态 */
  transform: translateY(0%);
  opacity: 1;
}

js部分

function Gellary(id, option) {
  //找到容器
  let container = document.getElementById(id)
  let ct = container.children
  //设置类样式
  if (container.className.indexOf('gellary') === -1) {
    container.className += ' gellary'
  }
  //判断矩阵的个数和元素的个数是否相等
  let flag = option.width && option.height && option.width * option.height !== ct.length
  if (flag) {
    throw 'width and height does not match children length'
  }
  //准备参数
  let defaulteOption = {
    defaultWidth: 130,
    defaultHeight: 40,
    activeHeight: 400,
    activeWidth: 340,
    animateDuration: 300,
  }
  //合并参数给option
  option = Object.assign({}, defaulteOption, option)
  //动态设置容器的宽度
  container.style.width = (option.width - 1) * option.defaultWidth + option.activeWidth + 'px'
  //声明时间的起点
  let lastRuntime = new Date(0)
  let runId = 0
  //声明激活图片的函数
  let activePicture = function (index) {
    /**
     * 此处控制激活图片的动作是在transition过渡结束后开始执行
     * 避免出现,图片卡顿现象
     */
    if (runId) {
      clearTimeout(runId)
    }
    let currentTime = new Date()
    if (currentTime - lastRuntime < option.animateDuration) {
      runId = setTimeout(function () {
        activePicture(index)
      }, option.animateDuration)
      return
    }
    lastRuntime = currentTime
    //转换当前激活的元素的下标为坐标
    let cx = index % option.width
    let cy = Math.floor(index / option.width)
    console.log(cx, cy)
    //遍历所有的坐标(x,y),把坐标转换成下标index
    for (let x = 0, xl = option.width; x < xl; x++) {
      for (let y = 0, yl = option.height; y < yl; y++) {
        //把坐标转换成下标
        let cindex = y * option.width + x
        //遍历所有元素
        let item = ct[cindex]
        if (cx === x && cy === y) {
          item.className = 'active'
          item.style.width = option.activeWidth + 'px'
          item.style.height = option.activeHeight + 'px'
        } else if (cx === x) {
          item.className = ''
          //和当前激活元素在同列的其它元素的样式
          item.style.width = option.activeWidth + 'px'
          item.style.height = option.defaultHeight + 'px'
        } else if (cy === y) {
          item.className = ''
          //和当前激活元素在同行的其它元素的样式
          item.style.width = option.defaultWidth + 'px'
          item.style.height = option.activeHeight + 'px'
        } else {
          item.className = ''
          item.style.width = option.defaultWidth + 'px'
          item.style.height = option.defaultHeight + 'px'
        }
      }
    }
  }
  //初始化第一张图片激活
  activePicture(0)

  //给每个div绑定事件
  for (let i = 0; i < ct.length; i++) {
    ct[i].addEventListener('mouseenter', function () {
      activePicture(i)
    })
  }

  // Array.prototype.forEach.call(ct, function (item, index) {
  //   item.addEventListener('mouseenter', function () {
  //     activePicture(index)
  //   })
  // })

  return { active: activePicture }
}

效果图:

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值