使用JavaScript练习动画最好的方式封面过渡

目录
  • 引言
  • 标记和样式
    • html代码
    • CSS代码
  • The JavaScript

引言

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

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

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

标记和样式

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

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

html代码

<div class="content">
	<div class="item">
		<span class="item__meta">2020</span>
		<h3 class="item__title">Alex Moulder</h3>
		<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>
		<h3 class="item__title">Aria Bennett</h3>
		<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>
		<h3 class="item__title">Jimmy Hughes</h3>
		<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>
		<h3 class="preview__title oh"><span class="oh__inner">Moulder</span></h3>
		<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">
			<h4 class="preview__column-title oh"><span class="oh__inner">Location</span></h4>
			<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">
			<h4 class="preview__column-title oh"><span class="oh__inner">Material</span></h4>
			<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 element
const body = document.body;
// .content element
const contentEl = document.querySelector('.content');
// frame element
const 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));
}

这就是这一切的结果

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

以上就是使用JavaScript练习动画最好的方式封面过渡的详细内容,更多关于JavaScript动画封面过渡的资料请关注我们其它相关文章!

(0)

相关推荐

  • 如何利用JS实现时间轴动画效果

    目录 css动画 什么是时间轴动画? 动画对象 动画函数 思考 总结 css动画 在前端开发中,一些简单的动效往往是使用 css3 的 @keyframes 来实现的 ,如: .div1 { width: 100px; height: 100px; background: red; animation: changeColor 2s; } @keyframes changeColor { 0% {background: red;} 50% {background: yellow;} 100% {

  • js实现酷炫倒计时动画

    本文实例为大家分享了js实现酷炫倒计时动画的具体代码,供大家参考,具体内容如下 前段时间和朋友去音乐餐厅吃饭,中间有个活动,然后看到他们软件公众号H5有个活动开始的倒计时的动画效果,于是想了下实现思路. <!DOCTYPE html> <html> <head>     <meta charset="utf-8" />     <title>js实现酷炫倒计时动画效果</title>     <style&g

  • JS使用window.requestAnimationFrame()实现逐帧动画

    window.requestAnimationFrame() 方法告诉浏览器您希望执行动画,并请求浏览器调用指定的函数在下一次重绘之前更新动画.该方法使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用. 如果你想做逐帧动画的时候,你应该用这个方法.这就要求你的动画函数执行会先于浏览器重绘动作.通常来说,被调用的频率是每秒60次,但是一般会遵循W3C标准规定的频率.如果是后台标签页面,重绘频率则会大大降低. 基本语法: requestID = window.requestAnimatio

  • 关于JavaScript实现动画时动画抖动的原因与解决方法

    目录 使用定时器实现动画出现卡顿的原因 requestAnimationFrame 的前世今生 requestAnimationFrame VS setInterval 参考资料 总结 前段时间在使用 JavaScript 做动画的时候发现做出来的动画会出现卡顿的现象,今天我们主要就来聊一下卡顿的原因以及如何解决这个问题. 使用定时器实现动画出现卡顿的原因 主要原因是浏览器无法确定定时器的回调函数的执行时机.以 setInterval 为例,当一个 setInterval 定时器被创建后,它的回

  • javascript 中动画制作方法 animate()属性

    animate是个非常冷门的方法,以至于百度和手册上都找不到相关的资料.当然通过一个小小的demo,我还是发现了方法的一些属 animate是所有dom元素都有的方法,可以用来最做过度动画,关键帧动画.这个方法可以更方便的让我们制作动 animate共有两个参数 (很可惜似乎没有回调函数,没发现) 关键帧 (参数可以是数组或对象,数组内包裹的也必须是对象)对象里的属性就是css属性和值了 动画属性设置 {参数数字或者对象} 目前发现的属性有以下 : duration: 动画时长 (单位毫秒) i

  • 使用JavaScript练习动画最好的方式封面过渡

    目录 引言 标记和样式 html代码 CSS代码 The JavaScript 引言 首先让我们来看一个镜头,这个镜头展示了几个过渡效果,其中之一就是我所说的 "封面过渡",一个黑色的封面以动画形式隐藏了一些内容,然后新的内容在封面上显现出来(其颜色与之前的不同). 我喜欢我们可以在网页中使用大量不同的动画来展示新内容的内容.所以我们今天将在一个简短的教程中看一下他的结构和动画的一些亮点. 我会使用GreenSock的GSAP作为效果的动画库. 标记和样式 我会以下面这个网站来实现这个

  • AngularJS中实现显示或隐藏动画效果的方式总结

    AngularJS 是一组用于创建单页Web应用的丰富框架,给构建丰富交互地应用带来了所有需要的功能.其中一项主要的特性就是Angular带来了对动画的支持. 本篇体验在AngularJS中实现在"显示/隐藏"这2种状态切换间添加动画效果. 通过CSS方式实现显示/隐藏动画效果 思路: →npm install angular-animage →依赖:var app = angular.module("app",["ngAnimate"]); →

  • JavaScript反弹动画效果的实现代码

    代码如下: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> #box{ width:200px; height:200px; position: absolute; top:0; left:200px; background:lightblue

  • javascript帧动画(实例讲解)

    前面的话 帧动画就是在"连续的关键帧"中分解动画动作,也就是在时间轴的每帧上逐帧绘制不同的内容,使其连续播放而成的动画.由于是一帧一帧的画,所以帧动画具有非常大的灵活性,几乎可以表现任何想表现的内容.本文将详细介绍javascript帧动画 概述 [分类] 常见的帧动画的方式有三种,包括gif.CSS3 animation和javascript git和CSS3 animation不能灵活地控制动画的暂停和播放.不能对帧动画做更加灵活地扩展.另外,gif图不能捕捉动画完成的事件.所以,

  • JavaScript中定义类的方式详解

    本文实例讲述了JavaScript中定义类的方式.分享给大家供大家参考,具体如下: Javascript本身并不支持面向对象,它没有访问控制符,它没有定义类的关键字class,它没有支持继承的extend或冒号,它也没有用来支持虚函数的virtual,不过,Javascript是一门灵活的语言,下面我们就看看没有关键字class的Javascript如何实现类定义,并创建对象. 一.定义类并创建类的实例对象 在Javascript中,我们用function来定义类,如下: function Sh

  • JavaScript中localStorage对象存储方式实例分析

    本文实例讲述了JavaScript中localStorage对象存储方式.分享给大家供大家参考,具体如下: [Local storage limitations]文章中提及JavaScript里的local storge的限制,例子中在localStorage里存储了一个bool型的数据,但是却没有像我们期待的一样进行存储. 当我们存储布尔型,数值型,字符串型时,localStorage对象会将我们存储的数据默认转为字符串字面量. localStorage[0] = false;// "fals

  • JavaScript中错误正确处理方式小结你用对了吗

    JavaScript的事件驱动范式增添了丰富的语言,也是让使用JavaScript编程变得更加多样化.如果将浏览器设想为JavaScript的事件驱动工具,那么当错误发生时,某个事件就会被抛出.理论上可以认为这些发生的错误只是JavaScript中的简单事件. 本文将会讨论客户端JavaScript中的错误处理.主要介绍JavaScript中的易犯错误.错误处理.异步代码编写等内容. 下面就让我们一起看看如何正确处理JavaScript中的错误. Demo演示 本文中使用的demo可以在GitH

  • JavaScript实现动画打开半透明提示层的方法

    本文实例讲述了JavaScript实现动画打开半透明提示层的方法.分享给大家供大家参考.具体如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"&g

  • javascript url几种编码方式详解

    1. escape() 不能直接用于URL编码,它的真正作用是返回一个字符的Unicode编码值.比如"春节"的返回结果是%u6625%u8282,escape()不对"+"编码主要用于汉子编码,现在已经不提倡使用了. 2. encodeURI()是javascript中真正用来对URL编码的函数.编码整个URL地址,但对特殊含义的符号";/?:@&=+$,#",也不进行编码.对应的解码函数是decodeURI(). 3. encodeU

  • 简述JavaScript提交表单的方式 (Using JavaScript Submit Form)

    最近做项目遇到用Javascript提交表单的问题, 之前也做过几次, 但是不够全面, 这次总结出了几种用JavaScript提交表单的方式, 并且对此作出了比较, 选出了一种最适合此项目的方式. 我目前正在为Sun Communication Suite做一个创建用户的小型系统,大家都知道我们可以通过表单,Ajax 和链接来访问服务器, 最简单的方法就是使用连接, 例如:<a href=UserServlet?event=SEARCH_MAILING_LIST&currentPage=1&

随机推荐