gsap timeline示例-实现滚动切换手机颜色

前言

最近使用gsap有点上瘾。看过一个手机官网滚动切换手机颜色的效果,初次见还是很炫。所以呢,就去研究了下,发现也不过如此。我们现在使用gsap来实现它。

首先来看最终效果:

gsap timeline示例-实现滚动切换手机颜色

实现原理

1. 首先整个dom结构被分为两个部分:背景及其文案、手机图片
2. 通过绝对定位让三个背景、三张图片分别重叠,保证元素在同一位置
3. 通过切换不同组的高度来展示不同的背景与图片

思路有了,那就来实现它

实现步骤

DOM结构

		<section class="change-color bg-black relative overflow-hidden h-screen">
            <div class="images absolute w-full h-screen z-10">
                <div class="image orange h-full w-1/2 absolute overflow-hidden left-1/3 top-0">
                    <figure  style="background-image: url(https://photographer-files.s3.us-east-2.amazonaws.com/orange.png);"></figure>
                </div>
                <div class="image blue h-0 w-1/2 absolute overflow-hidden left-1/3 top-0">
                    <figure  style="background-image: url(https://photographer-files.s3.us-east-2.amazonaws.com/blue.png);"></figure>
                </div>
                <div class="image black h-0 w-1/2 absolute overflow-hidden left-1/3 top-0">
                    <figure  style="background-image: url(https://photographer-files.s3.us-east-2.amazonaws.com/black.png);"></figure>
                </div>
            </div>
            <div class="background absolute w-full h-screen">
                <div class="text-box orange absolute overflow-hidden bg-orange-300 h-full w-1/2">
                    <div class="text absolute h-screen left-1/2 top-0 flex items-center" style="transform: translate(-50%, 0)">
                        <strong class="text-orange-500 text-9xl font-bold">Orange</strong>
                    </div>
                </div>
                <div class="text-box blue absolute overflow-hidden bg-blue-200 h-0 w-1/2">
                    <div class="text absolute h-screen left-1/2 top-0 flex items-center" style="transform: translate(-50%, 0)">
                        <strong class="text-blue-900 text-9xl font-bold">Blue</strong>
                    </div>
                </div>
                <div class="text-box black absolute overflow-hidden bg-gray-700 h-0 w-1/2 ">
                    <div class="text absolute h-screen left-1/2 top-0 flex items-center" style="transform: translate(-50%, 0)">
                        <strong class="text-gray-900 text-9xl font-bold">Black</strong>
                    </div>
                </div>
            </div>
        </section>

tips: 使用tailwind,具体样式应该一看class就能看懂

需要注意

  1. 图片使用的是背景而不是img,因为图片会根据高度变化而变化;
  2. 除了第一组橙色,其他两组初始高度都为0;
  3. 需要通过z-index来控制层级,这样能够在动画时不至于调整上一组的高度。

图片增加了一点样式:

.change-color figure{
    width: 461px;
    height: 604px;
    transform: translate(0, 20%);
}

现在我们就能通过控制台调整高度实现一定的效果了:
在这里插入图片描述

动画实现

首先我们要清楚,我们需要两组动画
一组用来固定整个结构
一组用来实现高度变化

	// 用来固定
	const section = document.querySelector(".change-color");
 	gsap.to(section, {
        scrollTrigger: {
            trigger: section,
            start: "top top",
            end: "300% top",
            pin: true,
            //markers: true,
        }
    });

使用gsap.timeline来执行高度变化的动画:

	const imgBlue = section.querySelector('.image.blue');
    const imgBlack = section.querySelector('.image.black');
    const textBlue = section.querySelector('.text-box.blue');
    const textBlack = section.querySelector('.text-box.black');
    
    // 创建一个时间线,还是使用section作为触发器
    const tl = gsap.timeline({
        scrollTrigger: {
          trigger: section,
          start: "top top",
          end: "300% top",
          scrub: true // 是否重复执行,这个能保证我们向上滚动时让动画反着执行
        }
    });
    
    /**
     * .to() 表示目标属性变化到什么状态
     * [textBlue, imgBlue, ...] 表示同时执行textBlue、imgBlue
     * { height: '100%', ... } 表示目标最终的状态
     * .to().to() 表示执行完前一个动画后执行下一个
     * 
     */ 
    tl.to([textBlue, imgBlue], { height: '100%' })
    .to([textBlack, imgBlack], { height: '100%' });

注意点

我们两个动画的end属性的第一个值都是300%,是单个组元素高度的三倍,是因为我们需要在滚动的时候保证高度变化的高度与滚动距离一致。当然也可以是其他值,更详细的属性解释,可以参照苹果官网动画解析之airpods滚动光影效果。

这样,我们的主要功能就全部实现了,但总感觉有点死板,那不如浅浅的再加一个进入的动画:

初始化动画

	const imgOrange = section.querySelector('.image.orange');
	
 	gsap.from(imgOrange, { 
        x: 800,
        transform: 'scale(0.8)',
        duration: 1.4,
        opacity: 0,
        ease: "expo.out",
        scrollTrigger: {
            trigger: section,
            start: "top top+=50%", // 这个保证只要元素进入页面,就能执行动画
            // markers: true,
        }
    })

这里使用from 表示目标元素从配置的属性恢复到我们css控制的初始状态
从这里也能看出来gsap创建动画的便利性

这样当页面进入的时候手机图片就会从右边想左移动的一个动画,同时也会变化透明度跟缩放比例。

完整代码

		<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
    <title>GSAP+TIMELINE</title>
</head>
<body>
    <main class="bg-slate-300 animate-demo ">
    	<!-- 这个是用来占位的,不知道为什么,前面必须要有一个有高度的元素才能实现滚动的功能 -->
    	<section style="height: 1px;" class="bg-black"></section>
        <section class="change-color bg-black relative overflow-hidden h-screen">
            <div class="images absolute w-full h-screen z-10">
                <div class="image orange h-full w-1/2 absolute overflow-hidden left-1/3 top-0">
                    <figure  style="background-image: url(https://photographer-files.s3.us-east-2.amazonaws.com/orange.png);"></figure>
                </div>
                <div class="image blue h-0 w-1/2 absolute overflow-hidden left-1/3 top-0">
                    <figure  style="background-image: url(https://photographer-files.s3.us-east-2.amazonaws.com/blue.png);"></figure>
                </div>
                <div class="image black h-0 w-1/2 absolute overflow-hidden left-1/3 top-0">
                    <figure  style="background-image: url(https://photographer-files.s3.us-east-2.amazonaws.com/black.png);"></figure>
                </div>
            </div>
            <div class="background absolute w-full h-screen">
                <div class="text-box orange absolute overflow-hidden bg-orange-300 h-full w-1/2">
                    <div class="text absolute h-screen left-1/2 top-0 flex items-center" style="transform: translate(-50%, 0)">
                        <strong class="text-orange-500 text-9xl font-bold">Orange</strong>
                    </div>
                </div>
                <div class="text-box blue absolute overflow-hidden bg-blue-200 h-0 w-1/2">
                    <div class="text absolute h-screen left-1/2 top-0 flex items-center" style="transform: translate(-50%, 0)">
                        <strong class="text-blue-900 text-9xl font-bold">Blue</strong>
                    </div>
                </div>
                <div class="text-box black absolute overflow-hidden bg-gray-700 h-0 w-1/2 ">
                    <div class="text absolute h-screen left-1/2 top-0 flex items-center" style="transform: translate(-50%, 0)">
                        <strong class="text-gray-900 text-9xl font-bold">Black</strong>
                    </div>
                </div>
            </div>
        </section>
    </main>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.4/gsap.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.4/ScrollTrigger.min.js"></script>
    <script>
        function ready(fn) {
            if (document.readyState !== 'loading') {
                fn();
            } else {
                document.addEventListener('DOMContentLoaded', fn);
            }
        }
        function changeColor() {  
            const section = document.querySelector(".change-color");

            const imgOrange = section.querySelector('.image.orange');
            const imgBlue = section.querySelector('.image.blue');
            const imgBlack = section.querySelector('.image.black');

            const textBlue = section.querySelector('.text-box.blue');
            const textBlack = section.querySelector('.text-box.black');
            
            gsap.to(section, {
                scrollTrigger: {
                    trigger: section,
                    start: "top top",
                    end: "300% top",
                    pin: true,
                    //markers: true,
                }
            });
            gsap.from(imgOrange, { 
                x: 800,
                transform: 'scale(0.8)',
                duration: 1.4,
                opacity: 0,
                ease: "expo.out",
                scrollTrigger: {
                    trigger: section,
                    start: "top top+=50%",
                    // markers: true,
                }
            })
            const tl = gsap.timeline({
                scrollTrigger: {
                trigger: section,
                start: "top top",
                end: "300% top",
                scrub: true
                }
            });
            
            /**
             * .to() 表示目标属性变化到什么状态
             * [textBlue, imgBlue, ...] 表示同时执行textBlue、imgBlue
             * { height: '100%', ... } 表示目标最终的状态
             * .to().to() 表示执行完前一个动画后执行下一个
             * 
             */
            tl.to([textBlue, imgBlue], { height: '100%' })
            .to([textBlack, imgBlack], { height: '100%' });
        }

        function init() {  
            gsap.registerPlugin(ScrollTrigger);
            changeColor();
        }
        ready(init);
    </script>
</body>
</html>

拿去就能跑,你可以试试~

写在最后

感谢你的阅读,如果你觉得有用,欢迎评论、点赞、转发~
当然也希望你能关注我的公众号:前端大乱炖
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/326439.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux用户提权

新建用户 用root账户修改文件&#xff0c;添加信任用户 使用sudo提权&#xff0c;可以使用 **root删除新建账户**

微服务接口工具Swagger2

##1、什么是Swagger? # 官网 https://swagger.io/核心功能 生成接口说明文档生成接口测试工具 2、SpringBoot集成Swagger2 1&#xff09;、添加依赖 <!-- swagger2 --><!-- https://mvnrepository.com/artifact/io.springfox/springfox-swagger2 --><depen…

【昕宝爸爸小模块】深入浅出之JDK21 中的虚拟线程到底是怎么回事(一)

➡️博客首页 https://blog.csdn.net/Java_Yangxiaoyuan 欢迎优秀的你&#x1f44d;点赞、&#x1f5c2;️收藏、加❤️关注哦。 本文章CSDN首发&#xff0c;欢迎转载&#xff0c;要注明出处哦&#xff01; 先感谢优秀的你能认真的看完本文&…

开发设计和迭代管理效率提升:PDManer元数建模

一、引言 在复杂多变的软件开发全生命周期中&#xff0c;数据库设计与建模扮演着举足轻重的角色。这一环节不仅关乎数据存储效率和应用性能优化&#xff0c;而且对于系统架构稳健性及业务逻辑清晰化具有深远影响。因此&#xff0c;选择一款功能强大且高效的数据库建模工具至关…

01背包问题dp数组理解dp[i][j-w]

文章目录 一、01背包是什么&#xff1f;二、例子三、解决思路dp(动态规划) 一、01背包是什么&#xff1f; 有 n 件物品和一个最多能背重量为 w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。 每件物品只能用一次&#xff0c;求解将哪些物品装入背包…

Angular系列教程之MVC模式和MVVM模式

文章目录 MVC模式MVVM模式MVC与MVVM的区别Angular如何实现MVVM模式总结 在讨论Angular的时候&#xff0c;我们经常会听到MVC和MVVM这两种设计模式。这两种模式都是为了将用户界面(UI)和业务逻辑分离&#xff0c;使得代码更易于维护和扩展。在这篇文章中&#xff0c;我们将详细介…

【光波电子学】基于MATLAB的多模光纤模场分布的仿真分析

基于MATLAB的多模光纤模场分布的仿真分析 一、引言 &#xff08;1&#xff09;多模光纤的概念 多模光纤&#xff08;MMF&#xff09;是一种具有较大纤芯直径的光纤结构&#xff0c;其核心直径通常在10-50微米范围内。与单模光纤&#xff08;SMF&#xff09;相比&#xff0c;…

nginx基础面试题以及配置文件解析和命令控制

目录 1、nginx是什么 2、nginx的特点 3、为什么中国大陆有&#xff1a;百度、京东、新浪、网易、腾讯、淘宝等这么多用户使用nginx 4、nginx 的内部技术架构 上一期我们配置安装了nginx接着讲一下nginx配置文件的解析和nginx 命令控制 感谢观看&#xff01;希望能够帮助到…

用原型实现Class的各项语法

本人之前对Class一直不够重视。平时对原型的使用&#xff0c;也仅限于在构造函数的prototype上挂属性。原型尚且用不着&#xff0c;更何况你Class只是原型的一颗语法糖&#xff1f; 直到公司开始了一个webgis项目&#xff0c;使用openlayers。看了下openlayers的代码&#xff0…

Sectigo有几种入门https证书买一年送一月

https证书是由CA认证机构颁发的数字证书&#xff0c;对网站传输数据进行加密&#xff0c;维护互联网环境安全&#xff0c;消除浏览器“不安全”提示。Digicert、Thawte、Sectigo等都是知名的CA认证机构&#xff0c;颁发的https证书中有很多都是入门级的https证书&#xff0c;其…

蓝桥杯基础数据结构(java版)

引言 数据结构数据结构。所以数据结构是一个抽象的概念。其目的是为了更好的组织数据方便数据存储。下面我们来看一些简单的数据储存方式 输入和输出 这里先介绍java的输入和输出。简单引入&#xff0c;不过多详细介绍&#xff0c;等我单一写一篇的时候这里会挂上链接 简单的…

【乱七八糟的经验】【个人】打羽毛球如何球球都接稳

从发球开始&#xff0c;球拍就不要离开视线之外。 为了达到这个目的&#xff0c;在待机时右手小臂就需要抬起一个角度&#xff0c;让球拍能在视野右下角&#xff1a; 然后球来时&#xff0c;球如果高&#xff0c;视线往上看&#xff0c;视野角度上移&#xff0c;球拍也要随之上…

代码随想录算法训练营Day22 | 491.非递减子序列、46.全排列、47.全排列||

LeetCode 491 非递减子序列 本题思路&#xff1a;什么情况下要搜集结果&#xff0c;可以写一个判断函数&#xff0c;当大小大于2的时候&#xff0c;并且&#xff0c;是非递减的&#xff0c;才能加入结果集中。需要注意的就是树层的一个去重操作。 class Solution {List<Int…

【PHP】PHP利用ffmreg获取音频、视频的详细信息

目录 一、目的 二、下载并安装ffmreg 三、PHP代码 四、运行结果 一、目的 使用PHP利用ffmreg获取音频、视频的详细信息&#xff0c;音视频总时长、码率、视频分辨率、音频编码、音频采样频率、实际播放时间、文件大小。 二、下载并安装ffmreg 1、下载地址&#xff1a;htt…

现在00后开发人员不晓得加班为何事嘛?

我招了两个做HTML5开端开发的人员&#xff0c;是从培训机构招来的&#xff0c;按理说他们应该很努学很用样才对的。他们上班第一天我就跟他们讲&#xff0c;我们不需要上、下班打卡&#xff1b;你们也不必太过担心迟到或早退。因为我们搞开发的人员首先是按自己的工作任务完成情…

【23种设计模式应用场景汇总】

23种设计模式应用场景汇总 设计模式是一种在软件开发中解决特定问题的通用解决方案。下面我将尝试将23种设计模式融入到一个场景中&#xff1a; 假设我们正在开发一个在线购物系统&#xff0c;我们可以使用以下设计模式&#xff1a; 1. 工厂方法模式&#xff1a;当用户在网站上…

云贝教育 |【OceanBase】OBCA认证考试预约流程

一、OBCA账号登录/注册&#xff0c;链接 https://www.oceanbase.com/ob/login/mobile?gotohttps%3A%2F%2Fwww.oceanbase.com%2Ftraining%2Fdetail%3Flevel%3DOBCA 注册完之后&#xff0c;请点击右上“登录”进行实名认证 OBCA考试报名链接&#xff1a;https://www.oceanbase.…

IDEA2023的激活与安装(全网最靠谱,最快捷的方式)

前言&#xff1a; 相信很多小伙伴已经开始了java的学习之旅&#xff0c;想要更快乐的学习当然少不了IDEA这个得力的开发工具软件。但是IDEA是付费的&#xff0c;免费版功能有太少&#xff0c;怎么才能既免费&#xff0c;又能使用上正式版呢&#xff01;当然还是激活啦&#xf…

数据结构与算法之美学习笔记:48 | B+树:MySQL数据库索引是如何实现的?

目录 前言算法解析总结引申 前言 本节课程思维导图&#xff1a; 作为一个软件开发工程师&#xff0c;你对数据库肯定再熟悉不过了。作为主流的数据存储系统&#xff0c;它在我们的业务开发中&#xff0c;有着举足轻重的地位。在工作中&#xff0c;为了加速数据库中数据的查找速…

maven导入无法拉取所需依赖

maven导入无法拉取所需依赖 1.原因2.解决搞定收工&#xff01; 1.原因 公司使用的是gradle&#xff0c;配置的私有云&#xff0c;maven里面配置私有云完全使用不了&#xff0c;无论配置国内还是国外的&#xff0c;导入的项目报错拉不到jar包。 <mirror><id>mirro…