JavaScript 5/30:Flex Panel Gallery即FLEX布局的图片库

JavaScript30 为Wes Bos推出的一项为期30天的挑战,旨在帮助人们用纯JavaScript来实现效果,初学者若想在JS方面快速精进,不妨一试。本题为第五题。

实现效果

点击任意一张图片,图片放大X倍,同时图片上下两方飞入文字,再点击已经展开的图片后,图片被压缩,同时顶端和底部的文字飞出。查看我的代码demo

页面基础布局

观察文档初始布局:在类名为.panels的父元素div之下,有5个类名为.panel的子div,这5个div内均包含3个p标签。文档内也已提供CSS样式及动画,做题者只需稍许补充并添加监听事件即可。

  <div class="panels">
    <div class="panel panel1">
      <p>Hey</p>
      <p>Let's</p>
      <p>Dance</p>
    </div>
    ......
    <div class="panel panel5">
      <p>Life</p>
      <p>In</p>
      <p>Motion</p>
    </div>
  </div>
复制代码

解题思路

CSS部分:

在本章中,大量运用flex布局知识,如需补课,推荐查阅阮一峰大神的博客:

  1. 设置父元素也就是最大的容器.panelsdisplay:flex,默认项目沿主轴方向,从左到右排列;
  2. 设置每个子元素即容器成员.paneldisplay:flex,并设置属性:
    • 设置flex: 1,flexflex-grow, flex-shrinkflex-basis的简写;
    • 设置justify-content: center,该属性规定项目在主轴上的对齐方式,center即沿主轴居中排列。
    • 设置flex-direction: column,该属性定义主轴的方向(即项目的排列方向),column表示主轴为垂直方向,起点在上沿;
    • 设置align-items: center,即项目在交叉轴上居中对齐。
  3. 设置点击图片后,文字的移动样式;
  4. 设置点击图片后,图片的flex值。
JS部分:
  1. 获取所有类名为.panel的元素;
  2. 为其添加click监听事件,触发调用函数,添加或去除样式,实现图片拉伸或压缩的效果;
  3. 为其添加transitionend监听事件,触发调用函数,添加或去除样式,实现顶端及底部文字飞入或飞出效果。

CSS部分代码

    html {
      box-sizing: border-box;
      background: #ffc600;
      font-family: 'helvetica neue';
      font-size: 20px;
      font-weight: 200;
    }

    body {
      margin: 0;
    }

    *,
    *:before,
    *:after {
      box-sizing: inherit;
    }

    .panels {
      min-height: 100vh;
      overflow: hidden;/*内容溢出元素框时,内容会被修剪,并且其余内容不可见 */
      display: flex;
    }

    .panel {
      background: #6B0F9C;
      box-shadow: inset 0 0 0 5px rgba(255, 255, 255, 0.1);
      color: white;
      text-align: center;
      align-items: center;
      /* Safari transitionend event.propertyName === flex */
      /* Chrome + FF transitionend event.propertyName === flex-grow */
      transition: font-size 0.7s cubic-bezier(0.61, -0.19, 0.7, -0.11),
      flex 0.7s cubic-bezier(0.61, -0.19, 0.7, -0.11),
      background 0.2s;
      font-size: 20px;
      background-size: cover;
      background-position: center;
      flex: 1;
      justify-content: center;
      display: flex;
      flex-direction: column;
    }


    .panel1 {background-image: url(https://source.unsplash.com/gYl-UtwNg_I/1500x1500);}
     ......
    .panel5 {background-image: url(https://source.unsplash.com/3MNzGlQM7qs/1500x1500);
    }

    /* Flex Items */

    .panel>* {
      margin: 0;
      width: 100%;
      transition: transform 0.5s;
      flex: 1 0 auto;
      display: flex;
      justify-content: center;
      align-items: center;
    }

    .panel>*:first-child {
      transform: translateY(-100%);
    }
    .panel.open-active>*:first-child {
      transform: translateY(0);
    }
    .panel>*:last-child {
      transform: translateY(100%);
    }
    .panel.open-active>*:last-child {
      transform: translateY(0);
    }

    .panel p {
      text-transform: uppercase;
      font-family: 'Amatic SC', cursive;
      text-shadow: 0 0 4px rgba(0, 0, 0, 0.72), 0 0 14px rgba(0, 0, 0, 0.45);
      font-size: 2em;
    }

    .panel p:nth-child(2) {
      font-size: 4em;
    }

    .panel.open {
      flex: 5;
      font-size: 40px;
    }
复制代码

JavaScript完整代码:

    const Panels = document.querySelectorAll('.panel');

    function clearOpen() {
      Panels.forEach(panel => panel.classList.remove('open'))
    }

    function toggelOpen() {
      this.classList.toggle('open');
    }

    function toggleActive(e) {
      if (e.propertyName.includes('flex')) {
        this.classList.toggle('open-active')
      }
    }

    Panels.forEach(panel => panel.addEventListener('click', toggelOpen));
    Panels.forEach(panel => panel.addEventListener('transitionend', toggleActive));
复制代码

知识点

Flex布局:

采用 Flex 布局的元素,称为 Flex 容器。它的所有子元素自动成为容器成员,称为 Flex 项目。容器默认存在两根轴:水平的主轴main axis和垂直的交叉轴cross axis

Flex容器属性:
  1. flex-direction属性决定主轴的方向(即项目的排列方向);
  2. flex-wrap属性定义,如果一条轴线排不下,如何换行;
  3. flex-flow属性是flex-direction属性和flex-wrap属性的简写形式;
  4. justify-content属性定义了项目在主轴上的对齐方式。
  5. align-items属性定义项目在交叉轴上如何对齐。
  6. align-content属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
Flex项目属性:
  1. order属性定义项目的排列顺序。数值越小,排列越靠前,默认为0。
  2. flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
  3. flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
  4. flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间。
  5. flex属性是flex-grow, flex-shrinkflex-basis的简写,默认值为0 1 auto
  6. align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。
介绍完基础知识再看本题就清晰很多了,本题嵌套了三个Flex容器,分别为:
  • .panels:使得子元素.panel横向等分排列;
  • .panel:使得其中的<p>纵向等分排列;
  • p:使得其中的文字垂直水平居中分布。 不过以上对Flex的介绍还不算详细,若想深入了解,可查阅这里
translateY

为实现顶端及底部文字飞入飞出的效果,题中使用了一个用法,即transform: translateY,可实现元素在Y轴方向上移动。

转载于:https://juejin.im/post/5ad3072851882555745a24c5

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值