首先让我们来看一个镜头,这个镜头展示了几个过渡效果,其中之一就是我所说的 "封面过渡",一个黑色的封面以动画形式隐藏了一些内容,然后新的内容在封面上显现出来(其颜色与之前的不同)。


我喜欢我们可以在网页中使用大量不同的动画来展示新内容的内容。所以我们今天将在一个简短的教程中看一下他的结构和动画的一些亮点。

我会使用GreenSock的GSAP作为效果的动画库。

标记和样式

我会以下面这个网站来实现这个效果


首先,我们的整个页面将是一个网格布局

html代码

<div class="content"> <div class="item">  <span class="item__meta">2020</span>  <h2 class="item__title">Alex Moulder</h2>  <div class="item__img"><div class="item__img-inner" style="background-image:url(img/1.jpg)"></div></div>  <p class="item__desc">I am only waiting for love to give myself up at last into his hands. That is why it is so late and why I have been guilty of such omissions.</p>  <a class="item__link">view</a> </div> <div class="item">  <span class="item__meta">2021</span>  <h2 class="item__title">Aria Bennett</h2>  <div class="item__img"><div class="item__img-inner" style="background-image:url(img/2.jpg)"></div></div>  <p class="item__desc">They come with their laws and their codes to bind me fast; but I evade them ever, for I am only waiting for love to give myself up at last into his hands.</p>  <a class="item__link">view</a> </div> <div class="item">  <span class="item__meta">2022</span>  <h2 class="item__title">Jimmy Hughes</h2>  <div class="item__img"><div class="item__img-inner" style="background-image:url(img/3.jpg)"></div></div>  <p class="item__desc">Clouds heap upon clouds and it darkens. Ah, love, why dost thou let me wait outside at the door all alone?</p>  <a class="item__link">view</a> </div></div>

CSS代码

main { padding: 1.5rem 2.5rem 3rem; height: 100vh; display: grid; grid-template-columns: 100%; grid-template-areas: 'frame' 'content'; grid-template-rows: min-content 1fr; grid-row-gap: 8vh;}

「内容划分将有以下风格,以显示网格中的项目」

.content { grid-area: content; max-width: 400px;}

@media screen and (min-width: 53em) { .content {  max-width: none;  display: grid;  grid-template-columns: repeat(3,1fr);  grid-template-rows: 100%;  grid-column-gap: 5vw; }}

我们只想在大屏幕上并排显示项目。所以我们添加了一个媒体查询。

对于项目的内部元素,我们将具有以下样式:

.item { margin-bottom: 5rem; display: grid; grid-template-columns: 100%; grid-template-rows: 1rem auto auto 1fr auto;}

.item__title { font-family: kudryashev-d-excontrast-sans, sans-serif; font-weight: 300; font-size: 2rem; margin-bottom: 0.5rem;}

.item__img { position: relative; overflow: hidden; width: 100%; aspect-ratio: 500/333;}

.item__img-inner { background-position: 50% 45%; background-size: cover; width: 100%; height: 100%;}

.item__desc { margin-top: 2.5rem; line-height: 1.1;}

.item__link { cursor: pointer; text-transform: lowercase; width: 100%; padding: 1rem; color: var(--color-text); border: 1px solid var(--color-border); border-radius: 2rem; text-align: center;}

.item__link:hover { background: var(--color-text); border-color: var(--color-text); color: var(--color-text-alt);}

@media screen and (min-width: 53em) { .item {  margin-bottom: 0; } .item__title {  font-size: clamp(1.25rem,3vw,2rem); }}

图像元素有一个嵌套结构,可以让我们做出一点缩放效果。这里有一个有趣的地方是宽高比属性,它允许我们在使用背景图像属性时根据其实际大小设置响应式图像尺寸。

当我们单击项目按钮时,我们将显示一个封面动画。这将是动画其比例变换以覆盖整个页面的两个元素:

<div class="overlay"> <div class="overlay__row"></div> <div class="overlay__row"></div></div>

让我们添加以下样式:

.overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; display: grid; grid-template-columns: 100%; pointer-events: none; grid-template-rows: repeat(2,1fr);}

.overlay__row { background: var(--color-overlay); transform: scaleY(0); will-change: transform;}

.overlay__row:first-child { transform-origin: 50% 0%;}

.overlay__row:last-child { transform-origin: 50% 100%;}

为每一“行”设置正确的变换原点将确保它们上下动画,“关闭”当前视图并隐藏它。

接下来,让我们看一下我们将看到的视图。此部分将称为“预览”,我们将添加以下内容:

<section class="previews"> <div class="preview">  <div class="preview__img"><div class="preview__img-inner" style="background-image:url(img/1_big.jpg)"></div></div>  <h2 class="preview__title oh"><span class="oh__inner">Moulder</span></h2>  <div class="preview__column preview__column--start">   <span class="preview__column-title preview__column-title--main oh"><span class="oh__inner">Alex Moulder</span></span>   <span class="oh"><span class="oh__inner">2020</span></span>  </div>  <div class="preview__column">   <h3 class="preview__column-title oh"><span class="oh__inner">Location</span></h3>   <p>And if it rains, a closed car at four. And we shall play a game of chess, pressing lidless eyes and waiting for a knock upon the door.</p>  </div>  <div class="preview__column">   <h3 class="preview__column-title oh"><span class="oh__inner">Material</span></h3>   <p>At the violet hour, when the eyes and back, turn upward from the desk, when the human engine waits.</p>  </div>  <button class="unbutton preview__back"><svg width="100px" height="18px" viewBox="0 0 50 9"><path vector-effect="non-scaling-stroke" d="m0 4.5 5-3m-5 3 5 3m45-3h-77"></path></svg></button> </div>

 <!-- preview -->

 <!-- preview -->

</section>

大图像将使用本教程中详细解释的显示/取消显示动画进行动画处理。这就是我们使用嵌套结构的原因,就像在项目图像上一样。对于我们想要通过转变(并被父级截断)来显示的文本,我们将使用 .oh > .oh__inner 结构。这背后的想法是转变oh__inner 元素以隐藏它。对于多行文本,我们将使用 JavaScript 动态添加此结构。我们 preview__column 分区中的段落将使用SplitType分成几行。

让我们添加以下样式以使线条魔术起作用:

.oh { position: relative;    overflow: hidden;}

.oh__inner { will-change: transform;    display: inline-block;}

.line { transform-origin: 0 50%; white-space: nowrap; will-change: transform;}

现在,让我们把这个宝贝做成动画

The JavaScript

让我们先定义和实例化一些东西

import { gsap } from 'gsap';import { Item } from './item';import { Preview } from './preview';

// body elementconst body = document.body;

// .content elementconst contentEl = document.querySelector('.content');

// frame elementconst frameEl = document.querySelector('.frame');

// 顶部和底部叠加的叠加元素const overlayRows = [...document.querySelectorAll('.overlay__row')];

const previews = [];[...document.querySelectorAll('.preview')].forEach(preview => previews.push(new Preview(preview)));

//项目实例列表const items = [];[...document.querySelectorAll('.item')].forEach((item, pos) => items.push(new Item(item, previews[pos])));

现在,当我们打开一个项目时,我们首先要把我们的内容设置为不能再点击。用一个类来完成。

然后,我们在显示预览内容后,隐藏所有那些我们想要动画化的线条和元素。preview-visible类帮助我们设置一些颜色和指针事件。我们还用它来隐藏我们在页面顶部的小框架,这样,一旦封面隐藏了初始视图,我们就可以用动画再次显示它。

通过将图像元素向一个方向平移,将内部元素(实际上包含了背景图像)向相反的方向平移,图像就不会被显示出来。

我们也最终显示了所有的线条和oh__inner元素。

const openItem = item => {

    gsap.timeline({        defaults: {            duration: 1,             ease: 'power3.inOut'        }    })    .add(() => {        // 指针事件没有指向内容        contentEl.classList.add('content--hidden');    }, 'start')

    .addLabel('start', 0)    .set([item.preview.DOM.innerElements, item.preview.DOM.backCtrl], {        opacity: 0    }, 'start')    .to(overlayRows, {        scaleY: 1    }, 'start')

    .addLabel('content', 'start+=0.6')

    .add(() => {        body.classList.add('preview-visible');

        gsap.set(frameEl, {            opacity: 0        }, 'start')        item.preview.DOM.el.classList.add('preview--current');    }, 'content')    // Image animation (reveal animation)    .to([item.preview.DOM.image, item.preview.DOM.imageInner], {        startAt: {y: pos => pos ? '101%' : '-101%'},        y: '0%'    }, 'content')

    .add(() => {        for (const line of item.preview.multiLines) {            line.in();        }        gsap.set(item.preview.DOM.multiLineWrap, {            opacity: 1,            delay:0.1        })    }, 'content')    // 动画框架元素    .to(frameEl, {        ease: 'expo',        startAt: {y: '-100%', opacity: 0},        opacity: 1,        y: '0%'    }, 'content+=0.3')    .to(item.preview.DOM.innerElements, {        ease: 'expo',        startAt: {yPercent: 101},        yPercent: 0,        opacity: 1    }, 'content+=0.3')    .to(item.preview.DOM.backCtrl, {        opacity: 1    }, 'content')

};

当我们关闭预览时,我们需要做一些反向动画

const closeItem = item => {

    gsap.timeline({        defaults: {            duration: 1,             ease: 'power3.inOut'        }    })    .addLabel('start', 0)    .to(item.preview.DOM.innerElements, {        yPercent: -101,        opacity: 0,    }, 'start')    .add(() => {        for (const line of item.preview.multiLines) {            line.out();        }    }, 'start')

    .to(item.preview.DOM.backCtrl, {        opacity: 0    }, 'start')

    .to(item.preview.DOM.image, {        y: '101%'    }, 'start')    .to(item.preview.DOM.imageInner, {        y: '-101%'    }, 'start')

    // 动画框架元素    .to(frameEl, {        opacity: 0,        y: '-100%',        onComplete: () => {            body.classList.remove('preview-visible');            gsap.set(frameEl, {                opacity: 1,                y: '0%'            })        }    }, 'start')

    .addLabel('grid', 'start+=0.6')

    .to(overlayRows, {        //ease: 'expo',        scaleY: 0,        onComplete: () => {            item.preview.DOM.el.classList.remove('preview--current');            contentEl.classList.remove('content--hidden');        }    }, 'grid')};

不要忘记事件监听器

for (const item of items) {    // 打开项目预览    item.DOM.link.addEventListener('click', () => openItem(item));    // 关闭项目预览    item.preview.DOM.backCtrl.addEventListener('click', () => closeItem(item));}

这就是这一切的结果

在动画进入时要有流畅的转场动画,并做一个快速的关闭动画,这样用户就不必等待很长时间来恢复最初的视图了。探索代码并尝试做一些其他的动画、计时和缓和,给它另一种感觉,看看哪些是有效的,哪些是无效的!

谢谢你观看到这里,拜拜✌️

本文由 mdnice 多平台发布

练习动画最好的方式:封面过渡相关推荐

  1. [vue] vue过渡动画实现的方式有哪些?

    [vue] vue过渡动画实现的方式有哪些? 1.使用vue的transition标签结合css样式完成动画 2.利用animate.css结合transition实现动画 3.利用 vue中的钩子函 ...

  2. CSS3动画(2D/3D转换、过渡、动画和多列)

    [index.html] <!DOCTYPE html> <html lang="en"> <head><meta charset=&qu ...

  3. android svg指纹录取动画_你知道几种前端动画的实现方式?

    随着互联网的持续发展,H5 页面作为与用户直接交互的表现层越来越复杂,呈现的形式也越来越丰富,从而也要求 H5 页面具有更多的花样性及动画效果.那前端实现动画效果的方式有哪些呢,大致有如下几种: 一. ...

  4. 手机端 自定义简单的下拉动画效果选择框 解决过渡失效

    手机端 自定义简单的下拉动画效果选择框 解决过渡失效 <template> // 弹出框触发 并显示选择结果<view class="header_top_sel" ...

  5. HTML5实现动画三种方式

    HTML5实现动画三种方式 编者注:作者以一个运动的小车为例子,讲述了三种实现HTML5动画的方式,思路清晰,动画不仅仅是Canvas,还有css3和javascript.通过合理的选择,来实现最优的 ...

  6. 练习动画最好的方式(一):锁链按钮

    练习动画最好的方式(一):锁链按钮 你能相信这张图片是由纯CSS绘画的吗? 这是国外一位大师的作品,作者并把整个制作的过程都录制了下来,虽然不知道总共花了多少时间,但这绝对是一个惊人的作品 我知道很多 ...

  7. css 实现动画的三种方式: transition 过渡、 transform 变形、 animation 关键帧动画

    1.transition 过渡动画: 1. 语法:1. transition: 属性是个复合属性 .2. transition: property duration timing-function d ...

  8. React-Router4 嵌套路由实现的两种方式以及路由过渡动画的实现方式

    刚学习react的路由 一个小的后台管理demo 目录结构 // 后台管理页面通常有两种布局方式 // 一种是没有导航栏的 登录页面 // 一种是含有导航栏的 各功能性页面 // 导航栏不需要每次都渲 ...

  9. React中过渡动画的编写方式

    文章目录 React的过渡动画 过渡动画库的介绍 CSSTransition(掌握) SwitchTransition(了解) TransitionGroup(了解) React的过渡动画 过渡动画库 ...

最新文章

  1. 【运筹学】线性规划数学模型 ( 单纯形法 | 第一次迭代 | 方程组同解变换 | 计算新单纯形表 | 计算检验数 | 入基变量选择 | 出基变量选择 )
  2. Web(浏览器)打开运行WinForm应用程序
  3. hdu 4430 Yukari's Birthday (简单数学 + 二分)
  4. IOS基础之NSString,NSMutableString,NSArray的基本使用
  5. 职场中 你要学习12种动物精神
  6. 【前端小小白】—每日5道面试题打卡(十五)
  7. scrapy爬取动态网页_scrapy_splash 爬取 js 加载网页初体验
  8. 实验一 Linux开发环境的配置 20145213祁玮 20145222黄亚奇
  9. 使用 webSocket 连接菜鸟打印(并获取当前电脑连接的打印机信息)
  10. 基于Matlab绘制演化博弈主体的演化轨迹
  11. split分割造成索引越界异常问题
  12. 如何下载安装weka包
  13. 扫描死链接的工具xenu
  14. 【AI全栈三】语音质量算法、评价指标 看一篇就够系列(附算法源码+干货)
  15. 谷歌公开自动驾驶新专利:通过眼睛注视向量,精确判断注意力
  16. 前端使用emoji表情
  17. LaTeX 字体、字号、字体样式
  18. javascript脚本语言电子书大全免费下载
  19. php5.6 7.1共存,分享一下php7和其他php多版本共存的配置教程
  20. 手机忘记密码的解决方法

热门文章

  1. 你敢说你热爱编程,你热爱学习吗?
  2. One-Stage与Two-Stage区别
  3. docker <应用分享> 上传镜像到 私有仓库 / 本地仓库,从私库拉取镜像
  4. Netty的深入浅出--10.接上一篇netty与protobuf整合的问题
  5. 哈趣H1和坚果微果C1哪个性价比更高,618该选择哪款千元投影仪?
  6. 程序设计语言发展回顾与展望
  7. 什么是段错误,段内,段间
  8. 大一学的计算机应用,计算机应用技术专业学生大一学年自我鉴定.doc
  9. OV7670_寄存器配置说明
  10. 基于Cent os 云服务器中SVN 服务器的搭建