手风琴特效这么飒,能用 JavaScript 实现吗?

手风琴效果一直是比较流行的页面特效之一,今天的将带大家实现一个不一样的手风琴效果,通过 JavaScript 实现全屏手风琴。最终效果如下:

知识点
  • 视口单位

  • 绝对定位与相对定位

  • transform 属性

  • 伪元素 before 和 after

  • 通过 CSS3 完成动画

  • JavaScript 添加类

本实验完整代码获取命令如下:

wget https://labfile.oss.aliyuncs.com/courses/2674/demo.zip
unzip demo.zip

模块基本结构

我们先学习模块的基本结构,新建 index.html 和 index.css,输入以下代码。

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>JavaScript 实现全屏手风琴</title>
  </head>
  <link rel="stylesheet" href="./index.css" />
  <body>
    <div class="cont">
      <!-- 手风琴的大盒子 -->
      <div class="cont__inner"></div>
    </div>
  </body>
</html>

index.css

/* 第一部分 */
*,
*:before,
*:after {
  /* box-sizing: border-box,为元素指定的任何内边距和边框都将在已设定的宽度和高度内进行绘制,不会因为设置了边距而使元素宽高改变 */
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  background: #1f1f1f;
  font-family: "Open Sans", Helvetica, Arial, sans-serif;
}

.cont {
  position: relative;
  overflow: hidden;
  height: 100vh;
  padding: 80px 70px;
}

.cont__inner {
  position: relative;
  height: 100%;
  background: #fff;
}

执行如下操作预览页面:

预览效果:

注意:padding 是自己加的,跟代码无关,主要是方便理解 padding 的作用在哪,背景色也只是为了显示 cont__inner。后续会删除。

代码重点讲解之—— viewport

viewport:可视窗口,也就是浏览器。视口单位主要包括以下 4 个:

  • vw : 1vw 等于视口宽度的 1%。

  • vh : 1vh 等于视口高度的 1%。

  • vmin : 选取 vw 和 vh 中最小的那个。

  • vmax : 选取 vw 和 vh 中最大的那个。

100vh 代表整个浏览器可见页面的高度,100vw 就是整个宽度。

模块布局

修改 index.html,在 cont__inner 下加入以下代码:

<div class="cont__inner">
  <!-- 每一块图片 -->
  <div class="el"></div>
</div>

修改 index.css,新增其样式:

/* 第二部分 */
.el {
  position: absolute;
  left: 0;
  top: 0;
  width: 19.2%;
  height: 100%;
  background: #ccc;
}

预览效果:

这只是其中一个模块,修改 index.html 加入剩下的模块:

<div class="cont__inner">
  <!-- 每一块图片 -->
  <div class="el"></div>
  <div class="el"></div>
  <div class="el"></div>
  <div class="el"></div>
  <div class="el"></div>
</div>

由于 .el 使用了绝对定位,这个时候模块肯定都会全部叠加在最左边,所以我们需要修改 index.css,加入以下代码:

/* :nth-child(n) 选择器匹配属于其父元素的第 n 个子元素,不论元素的类型。*/
/* 这里代表第一个el  */
.el:nth-child(1) {
  /* -webkit 前缀是表示兼容有 webkit 的浏览器,
    webkit 内核的浏览器有谷歌浏览器、Safari 浏览器、搜狗高速浏览器等 */
  -webkit-transform: translate3d(0%, 0, 0);
  transform: translate3d(0%, 0, 0);
  -webkit-transform-origin: 50% 50%; /* 设置旋转元素的基点位置 */
  transform-origin: 50% 50%;
}
.el:nth-child(2) {
  -webkit-transform: translate3d(105.2083333333%, 0, 0);
  transform: translate3d(105.2083333333%, 0, 0);
  -webkit-transform-origin: 155.2083333333% 50%;
  transform-origin: 155.2083333333% 50%;
}

.el:nth-child(3) {
  -webkit-transform: translate3d(210.4166666667%, 0, 0);
  transform: translate3d(210.4166666667%, 0, 0);
  -webkit-transform-origin: 260.4166666667% 50%;
  transform-origin: 260.4166666667% 50%;
}

.el:nth-child(4) {
  -webkit-transform: translate3d(315.625%, 0, 0);
  transform: translate3d(315.625%, 0, 0);
  -webkit-transform-origin: 365.625% 50%;
  transform-origin: 365.625% 50%;
}

.el:nth-child(5) {
  -webkit-transform: translate3d(420.8333333333%, 0, 0);
  transform: translate3d(420.8333333333%, 0, 0);
  -webkit-transform-origin: 470.8333333333% 50%;
  transform-origin: 470.8333333333% 50%;
}

预览效果:

代码重点讲解之—— transform-origin

transform-origin 是变形原点,原点就是元素绕着旋转或变形的点,该属性只有在设置了 transform 属性的时候才起作用,如果在不设置的情况下,元素的基点默认的是其中心位置。

语法:

transform-origin: x-axis y-axis z-axis;
  • x-axis:定义视图被置于 X 轴的何处。

  • y-axis:定义视图被置于 Y 轴的何处。

  • z-axis:定义视图被置于 Z 轴的何处。

模块样式

修改 index.html,在第一个 .el 下加入以下代码:

<!-- 每一块图片 -->
<div class="el">
  <!-- 图片、文字、按钮部分 -->
  <div class="el__overflow">
    <div class="el__inner">
      <!-- 主体图片和遮罩层部分 -->
      <div class="el__bg"></div>
      <!-- 图片中间文字内容部分 -->
      <div class="el__preview-cont">
        <h2 class="el__heading">Section 1</h2>
      </div>
      <!-- 图片放大后的标题和关闭按钮部分 -->
      <div class="el__content">
        <div class="el__text">Whatever</div>
        <div class="el__close-btn"></div>
      </div>
    </div>
  </div>
  <!--数字部分 -->
  <div class="el__index">
    <div class="el__index-back">1</div>
    <div class="el__index-front">
      <div class="el__index-overlay" data-index="1">1</div>
    </div>
  </div>
</div>

分析一下 .el 的结构,每个 .el 包含两部分,一部分是包含了图片、文字以及按钮(el__overflow),它的高度需要继承自父级(.el)的百分百,另一部分是底部的数字部分(el__index)。

主题图片及遮罩层样式

修改 index.css,新增以下代码:

/* 第三部分 */
.el__overflow {
  overflow: hidden;
  position: relative;
  height: 100%;
}
.el__inner {
  overflow: hidden;
  position: relative;
  height: 100%;
}

.el__bg {
  position: relative; /* 设置元素为相对定位,为了让之后的 .el__bg:before 伪元素设置相对定位时是相对这个元素的 */
  width: calc(100vw - 140px);
  /* 设置 div 元素的宽度为当前窗口高度 -140px */
  height: 100%;
  background: palegoldenrod;
}

为了便于理解,在这里我们取消掉 .el__overflow 和 .el__inner 的overflow:hidden

这就是模块点击之后展开的部分(.el__bg)。

注意:取消后的 overflow:hidden 记得还原。

伪元素 before 和 after

.el__bg:before 和 .el__bg:after 伪元素结构相当于如下:

<div class="el__bg">
  <div class="before"></div>
  <div class="after"></div>
</div>

打开终端,执行以下命令,获取所需图片:

wget https://labfile.oss.aliyuncs.com/courses/2674/onepgscr-3.jpg
wget https://labfile.oss.aliyuncs.com/courses/2674/onepgscr-4.jpg
wget https://labfile.oss.aliyuncs.com/courses/2674/onepgscr-5.jpg
wget https://labfile.oss.aliyuncs.com/courses/2674/onepgscr-6.jpg
wget https://labfile.oss.aliyuncs.com/courses/2674/onepgscr-7.jpg

修改 index.css,新增以下代码:

.el__bg:before {
  content: "";
  position: absolute;
  left: 0;
  top: -5%;
  width: 100%;
  height: 110%;
  background-size: cover; /* 覆盖所有背景区域 */
  background-position: center center; /* 居中 */
}
.el:nth-child(1) .el__bg {
  -webkit-transform: translate3d(0%, 0, 0); /* 设置图片的位置 */
  transform: translate3d(0%, 0, 0);
}
.el:nth-child(1) .el__bg:before {
  background-image: url("onepgscr-3.jpg"); /* 把图片放在伪元素中 */
}

预览效果:

同样的道理,在每个剩下的 .el 中加入第一个模块的代码,并修改相应的数字(比如第二个模块就都把 1 改成 2):

修改 index.css,新增以下代码:

.el:nth-child(2) .el__bg {
  -webkit-transform: translate3d(-19.2%, 0, 0);
  transform: translate3d(-19.2%, 0, 0);
}
.el:nth-child(2) .el__bg:before {
  background-image: url("onepgscr-4.jpg");
}
.el:nth-child(3) .el__bg {
  -webkit-transform: translate3d(-38.4%, 0, 0);
  transform: translate3d(-38.4%, 0, 0);
}
.el:nth-child(3) .el__bg:before {
  background-image: url("onepgscr-5.jpg");
}
.el:nth-child(4) .el__bg {
  -webkit-transform: translate3d(-57.6%, 0, 0);
  transform: translate3d(-57.6%, 0, 0);
}
.el:nth-child(4) .el__bg:before {
  background-image: url("onepgscr-6.jpg");
}
.el:nth-child(5) .el__bg {
  -webkit-transform: translate3d(-76.8%, 0, 0);
  transform: translate3d(-76.8%, 0, 0);
}
.el:nth-child(5) .el__bg:before {
  background-image: url("onepgscr-7.jpg");
}

预览效果:

篇幅有限,欢迎大家来实验楼学习完整课程及代码。

本课程是 JavaScript 的简单课,所以对于 JavaScript 部分是比较简单且容易理解的,希望大家多多动手,不要只进行简单的复制粘贴,才能更好的学习本课程。

????????????  点击阅读原文,了解课程完整内容!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值