本篇文章主要使用gsap中的ScrollTrigger去实现页面动画
老样子,来一句励志诗句洗洗脑先!
大鹏一日同风起,扶摇直上九万里。
效果视频
----> 视频地址 注:视频需要下载后方可观看
代码实现前期准备
需要引入gsap.min.js和ScrollTrigger.min.js两个js文件
https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/gsap.min.js
https://cdnjs.cloudflare.com/ajax/libs/gsap/3.11.4/ScrollTrigger.min.js
GSAP
首先我们要知道这个库能做什么,The GreenSock Animation Platform (GSAP)是一个功能十分强大的动画平台,可以帮助我们实现大部分的动画需求,构建高性能的、适用于所有主要浏览器的高性能动画;GSAP非常的灵活,可以在任何框架上处理页面能够所有通过js改变的元素,不仅可以对div的css属性进行动画,还是SVG、React、Vue、WebGL,甚至和Threejs一起使用。并解决不同浏览器上存在的兼容问题。
除了GSAP核心库外,还有很多实用的插件,比如结合ScrollTrigger插件,我们可以实现非常震撼的滚动触发效果;同时也不需要担心响应式的问题,GSAP确保项目响应迅速、高效且流畅。
ScrollTrigger
ScrollTrigger是基于GSAP实现的一款高性能页面滚动触发HTML元素动画的插件。
通过ScrollTrigger使用最少的代码创建令人叹为观止的滚动动画。我们需要知道ScrollTrigger是基于GSAP实现的插件,ScrollTrigger是处理滚动事件的,而真正处理动画是GSAP,二者组合使用才能实现非常炫酷的滚动动画。
下面是ScrollTrigger的一些属性方法
| 属性 | 描述 | |
|---|---|---|
| animation | 应该由ScrollTrigger控制的GSAP Tween或Timeline实例。每个ScrollTrigger只能控制一个动画,但您可以将所有动画包装在一个时间轴中(最好),或者创建多个ScrollTrigger(如果愿意)。 | |
| anticipatePin | 数字-如果您固定较大的部分/面板,当您快速滚动时,您可能会注意到固定过程中的轻微延迟。这是因为大多数现代浏览器在一个单独的线程上处理滚动重绘,所以在锁定的时候,浏览器可能已经绘制了预先锁定的内容,使其在大约60分之一秒内可见。唯一抵消这种影响的方法是让ScrollTrigger监控滚动速度并预测pin,稍微早一点应用它以避免未固定内容的闪烁。expectePin:1的值通常很好,但您可以减少或增加该值以控制其进行固定的时间。然而,在许多情况下,您不需要任何PredictePin(默认值为0)。 | |
| containerAnimation | 一种流行的效果是创建与垂直滚动相关的水平移动部分,但由于水平移动不是本机滚动,常规滚动触发器无法知道何时(例如)元素水平进入视图,因此必须告诉滚动触发器监视容器的[水平]动画,以知道何时触发,比如containerAnimation:yourTween。请在此处查看演示,并在此处查看更多信息。警告:容器的动画必须使用线性减缓(减缓:“无”)。此外,基于containerAnimation的ScrollTriggers上没有固定和捕捉功能。您应该避免水平设置触发器元素的动画,或者如果这样做,只需根据设置触发器动画的距离偏移开始/结束值即可。 | |
| end | String: 以使用诸如“top”、“bottom”、“center”(或“left”和“right”(如果水平:true)之类的关键字或诸如“80%”之类的百分比或诸如“100px”之类的像素值。max”是一个特殊的关键字,指示最大滚动位置。Number-一个精确的滚动值,因此当视口/滚动条滚动精确200像素时,将触发200。还可以传函数。 | |
| endTrigger | 元素(或元素的选择器文本),其在正常文档流中的位置用于计算ScrollTrigger结束的位置。您不需要定义endTrigger,除非它与trigger元素不同,因为这是默认值。 | |
| fastScrollEnd | Number-如果为true,则如果您以高于特定速度(默认2500px/s)的速度离开当前ScrollTrigger的触发区域,则会强制当前ScrollTrigger的动画完成。这有助于在用户快速滚动时避免重叠动画。您可以为最小速度指定一个数字,因此只有当速度超过3000px/s时,fastScrollEnd:3000才会激活。 | |
| horizontal | 布尔值-默认情况下,它假定您的安装程序使用垂直滚动,但只需设置水平:如果您的安装程序使用水平滚动,则为true。 | |
| id | String—ScrollTrigger实例的任意唯一标识符,可与ScrollTrigger一起使用。getById()。此id也会添加到标记中。 | |
| invalidateOnRefresh | 布尔值-如果为true,则与ScrollTrigger关联的动画将在每次发生refresh()时调用其invalidate()方法(通常在resize时)。这将清除所有内部记录的起始值。 | |
| markers | Object Boolean-添加在开发/故障排除期间有用的标记。标记:true使用默认值添加它们(startColor:“绿色”,endColor:“红色”,fontSize:“16px”,fontWeigth:“正常”,缩进:0),但您可以使用类似对象的标记来自定义它们:{startColor:“白色”,endColor:“白色”,fontSize:“18px”,fontWeight:“粗体”,缩进:20}。 | |
| once | Boolean-如果为true,则一旦到达结束位置一次,ScrollTrigger就会终止()本身。这会导致它停止侦听滚动事件,并有资格进行垃圾收集。这最多也只会调用一次onEnter。它不会终止关联的动画。当您只想在向前滚动时播放一次动画,而从不重置或重放时,它非常适合。它还将toggleActions设置为“play none none”。 | |
| onEnter | 函数-当滚动位置向前移动超过“开始”时的回调(通常是当触发器滚动到视图中时)。它接收一个参数—ScrollTrigger实例本身,它具有progress、direction、isActive和getVelocity()等属性/方法。 | |
| onEnterBack | 函数-当滚动位置向后移动超过“结束”时的回调(通常是当触发器滚动回视图时)。它接收一个参数—ScrollTrigger实例本身,它具有progress、direction、isActive和getVelocity()等属性/方法。 | |
| onLeave | 函数-当滚动位置向前移动超过“结束”时的回调(通常是当触发器滚动出视图时)。它接收一个参数—ScrollTrigger实例本身,它具有progress、direction、isActive和getVelocity()等属性/方法。 | |
| onLeaveBack | 函数-当滚动位置向后移动超过“开始”时的回调(通常当触发器向后滚动超过开始)。它接收一个参数—ScrollTrigger实例本身,它具有progress、direction、isActive和getVelocity()等属性/方法。 | |
| onRefresh | 函数-刷新发生时的回调(通常是调整大小事件),强制ScrollTrigger重新计算其所有位置。它接收一个参数—ScrollTrigger实例本身,它具有progress、direction、isActive和getVelocity()等属性/方法。 | |
| onUpdate | 函数-每当ScrollTrigger的进度发生变化(意味着滚动位置发生变化)时调用的回调。如果应用了数字拖动,请记住,在滚动位置停止后,关联的动画将继续拖动一段时间,因此,如果您的目标是在动画更新时更新某些内容,最好对动画本身应用onUpdate,而不是滚动触发器。onUpdate回调接收一个参数—ScrollTrigger实例本身,它具有progress、direction、isActive和getVelocity()等属性/方法。 | |
| onScrubComplete | 函数-当数字清理完成时的回调。这仅在应用数值磨砂(如磨砂:1)时有用。回调接收一个参数—ScrollTrigger实例本身,它具有progress、direction、isActive和getVelocity()等属性/方法。 | |
| onSnapComplete | Function—用于完成捕捉的回调。这仅适用于定义了捕捉的情况。如果/当用户(或其他任何东西)以任何方式与滚动进行交互时,快照将被取消,因此在这种情况下,onSnapComplete将不会被触发。回调接收一个参数—ScrollTrigger实例本身,它具有progress、direction、isActive和getVelocity()等属性/方法。 | |
| onToggle | 函数-当ScrollTrigger从非活动切换到活动或以其他方式切换时的回调。这通常是当滚动位置沿任一方向移动超过“开始”或“结束”时,但如果它在同一个刻度上同时超过这两个位置,例如如果用户滚动速度极快,则不会触发onToggle,因为状态没有改变。您可以通过检查isActive属性来进行切换,经常使用这个回调来代替onEnter、onLeave、onEnterBack和onLeaveBack。它接收一个参数—ScrollTrigger实例本身,它具有progress、direction、isActive和getVelocity()等属性/方法。 | |
| pin | 布尔-字符串-元素-在ScrollTrigger处于活动状态期间应固定的元素(或元素的选择器文本),这意味着当其余内容继续在其下方滚动时,它将显示为“粘住”在其起始位置。只允许一个固定元素,但它可以包含任意多个元素。设置pin:true将导致其锁定触发器元素。警告:不要为固定的元素本身设置动画,因为这会导致测量结果丢失(ScrollTrigger针对性能进行了高度优化,并尽可能进行预计算)。相反,可以嵌套对象,以便仅在固定的元素内设置元素的动画。 | |
| pinnedContainer | 元素-字符串-如果您的ScrollTrigger的trigger/endTrigger元素位于被另一个ScrollTrigger固定的元素内(非常罕见),那么无论该固定持续多长时间,都会导致开始/结束位置被抛出,因此您可以将pinnedContainer设置为该父/容器元素,以便ScrollTrigger相应地计算这些偏移。 | |
| pinReparent | 布尔值-如果为true,则当固定元素处于活动固定状态时,它将被重新租入<主体>,以便它可以转义任何包含块的祖先。如果在固定时注意到奇怪的行为(如固定的元素突然移动,然后随着滚动一起移动),则可能会对破坏位置的祖先元素进行变换或更改:固定行为(这是浏览器的事情,而不是ScrollTrigger)。最好是将项目设置为避免这些问题,因为重新租用可能会很昂贵,但如果你无法避免它们,pinrepart:true可以帮助你摆脱困境。仅在必须时使用此功能。警告:如果您有依赖于特定嵌套的CSS规则,而这些嵌套将受到重新租用的影响,那么它们将被破坏。 | |
| pinSpacer | 元素-通常情况下,ScrollTrigger会在内部创建一个来包裹固定的元素,但在极少数情况下,当ScrollTrigger刷新时,它会导致iframe刷新(如在窗口调整大小时),因此此功能允许您指定一个应用作间隔符的元素,而不是内部创建的元素。这样,ScrollTrigger就不会在刷新期间删除/添加它,从而保持iframe内容的完整性。 | |
| pinSpacing | Boolean - String-默认情况下,将在底部(或水平:true的右侧)添加填充,以向下推动其他元素,以便在固定的元素取消固定时,以下内容可以完美捕捉。否则,可能会在固定元素下滚动。通过设置pinSpacing:false,可以告诉ScrollTrigger不要添加任何填充。如果您希望它使用margin而不是padding,可以设置pinSpacing:“margin”。注意:pinSpacing在大多数情况下都有效,但它实际上取决于您设置DOM和CSS的方式。例如,如果在具有display:flex或position:absolute的父元素中固定某个元素,则额外的填充不会向下/向右推动其他元素,因此可能需要手动将其隔开。插脚间距只是一种在大多数情况下都可以使用的便利。 | |
| pinType | “fixed”-“transform”-默认情况下,只有当滚动条是时,position:fixed才用于固定,否则将使用变换(因为position:fixed在各种嵌套场景中都不起作用),但您可以通过设置pinType:“fixed”强制ScrollTrigger使用position:fixed。通常这是没有必要或没有帮助的。请注意,如果设置CSS属性will change:transform,浏览器会将其视为应用了转换,中断位置:固定元素(这与ScrollTrigger/GSAP无关)。 | |
| preventOverlaps | 布尔-字符串-当ScrollTrigger即将触发动画时,此功能激活;它会查找之前基于scrollTrigger的动画,并将这些之前的动画强制到其最终状态,从而避免难看的重叠。如果为true,它将影响前面的所有ScrollTriggers。可以使用任意字符串将其效果限制为仅对具有匹配字符串的其他字符串有效。因此preventOverlaps:“group1”只会影响其他具有preventOverlaps:“group1”的ScrollTriggers。 | |
| refreshPriority | 数字-只要您按照ScrollTriggers在页面上发生的顺序(从上到下或从左到右)创建ScrollTriggers,就不太可能需要定义刷新优先级。。。我们强烈建议这样做。否则,请使用refreshPriority影响ScrollTriggers的刷新顺序,以确保将固定距离添加到页面下方后续ScrollTriggers的开始/结束值中(这就是为什么顺序很重要)。有关详细信息,请参阅sort()方法。刷新优先级为1的ScrollTrigger将比刷新优先级为0(默认值)的ScrollTrigger更早刷新。欢迎您也使用负数,您可以将相同的数字分配给多个ScrollTriggers。 | |
| scroller | 字符串-元素-默认情况下,滚动条是视口本身,但如果您想向可滚动的添加滚动触发器,只需将其定义为滚动条即可。您可以使用诸如“#elementID”之类的选择器文本或元素本身。 | |
| scrub | 布尔-数字-将动画的进度直接链接到滚动条,使其像一个洗涤器。您可以应用平滑,以便playhead需要一点时间才能赶上滚动条的位置!它可以是以下任何一种布尔-拖动:true将动画的进度直接链接到ScrollTrigger的进度。Number-播放头“追赶”所需的时间(以秒为单位),因此“拖动:0.5”将导致动画的播放头花费0.5秒来追赶滚动条的位置。这对解决问题很好。 | |
| snap | Number - Array - Function - Object -“labels”-“labelsDirective”-允许您在用户停止滚动后捕捉到某些进度值(介于0和1之间)。所以捕捉:0.1将以0.1的增量捕捉(10%、20%、30%等)。捕捉:[0,0.1,0.5,0.8,1]只会让它停留在其中一个特定的进度值上。太长了具体看英文版。 | |
| start | 字符串-数字-函数-确定ScrollTrigger的起始位置。它可以是以下任一项:字符串-描述触发器上的一个位置和滚动条上必须满足的一个位置,以便启动滚动触发器。例如,“top center”表示“当触发器的顶部碰到滚动条的中心时”(默认情况下滚动条是视口)。“底部80%”表示“当触发器底部从视口顶部向下80%”(假设垂直滚动)。您可以使用诸如“top”、“bottom”、“center”(或“left”和“right”(如果水平:true)之类的关键字或诸如“80%”之类的百分比或诸如“100px”之类的像素值。百分比和像素始终相对于元素/滚动条的顶部/左侧。您甚至可以使用复杂的相对值,如“top-bottom-=100px”,这意味着“当触发器顶部达到视口/滚动条底部上方100px时”数字-一个精确的滚动值,因此当视口/滚动条滚动精确200像素时,将触发200。Function—每当ScrollTrigger计算其位置时(通常在创建时和滚动器调整大小时)调用的函数。它应该返回一个字符串或数字,如上所述。这使得动态计算值变得很容易。与所有回调一样,该函数接收ScrollTrigger实例本身作为唯一参数,因此,例如,您可以将位置基于前一个ScrollTrigger的end,比如start:self=>self。上一页()。终止这是一个静态位置,在创建ScrollTrigger和调整scroller大小时根据正常文档流中的位置计算得出。它不会不断重新计算,因此,例如,如果设置触发器/结束触发器的动画,它不会不断相应地更新开始/结束值,因为ScrollTrigger对性能进行了高度优化。您可以调用ScrollTrigger。refresh()强制重新计算。默认值为“top-bottom”,除非设置了pin:true,在这种情况下,默认值为“top-top”。 | |
| toggleActions | 字符串-确定如何在4个不同的切换位置控制链接的动画-按该顺序为onEnter、onLeave、ONNETRBACK和ONLEAVACK。默认值为play none none。因此,toggleActions:“play pause resume reset”(播放暂停恢复重置)将在输入时播放动画,在离开时暂停动画,在再次向后输入时恢复动画,在滚动到开始处后重置(回放到开始处)。您可以对每个操作使用以下任何关键字:“播放”、“暂停”、“恢复”、“重置”、“重新启动”、“完成”、“反转”和“无”。-toggleClass | String - Object-当ScrollTrigger切换为活动/非活动时,向元素(或多个元素)添加/删除类。它可以是以下任一项:String—要添加到触发器元素的类的名称,如toggleClass:“active”Object-要为触发器以外的元素切换类,请使用对象语法,如toggleClass:{目标:“.my selector”,className“active”}。“目标”可以是选择器文本、对元素的直接引用或元素数组。请注意,toggleActions不适用于toggleClass。要以不同的方式切换类名,请使用回调函数(oneter、onLeave、onLeaveBack和onEnterBack) |
| trigger | 字符串 | 元素-元素(或元素的选择器文本),其在正常文档流中的位置用于计算ScrollTrigger的开始位置。 |
废话不多说我们直接上代码 come on
目录结构
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>官网</title>
<link rel="stylesheet" href="./css/index.css" />
</head>
<body>
<!-- 第一屏 -->
<section class="screen section1">
<div class="kv-content">
<img src="./image/farid-mardanov-Dev-PPWkskY-unsplash.jpg" alt="" />
</div>
</section>
<!-- 第二屏 -->
<section class="screen section2">
<div class="summary-content">
<video src="./image/532680_720p.mp4" class="summary"></video>
<p class="text1">
优雅^ <br />
落日余晖映大海,晚霞绚烂彩云开。
</p>
<p class="text2">大海倚天迎落日,晚霞如火燃红晖。</p>
</div>
</section>
<!-- 第三屏 -->
<section class="screen section3">
<div class="color-img">
<img
src="./image/josh-hild-9eQqt9taDeI-unsplash.jpg"
alt=""
class="color1"
/>
<img
src="./image/josh-hild-bu3aHCbQ308-unsplash.jpg"
alt=""
class="color2"
/>
<img
src="./image/josh-hild-dEp3dWEWPOs-unsplash.jpg"
alt=""
class="color3"
/>
<img
src="./image/josh-hild-ZhX8QssVbrU-unsplash.jpg"
alt=""
class="color4"
/>
</div>
</section>
<!-- 第四屏 -->
<section class="screen section4">
<div class="parallel">
<div class="page1">
<p class="title">美学创作大师</p>
<video src="./image/aaa.mp4" class="video1" muted></video>
<div class="info">
重塑每一秒 <br>
自在享受视频拍摄吧!理想身材相机直出,让每一刻的出境更自由纯粹。
</div>
</div>
<div class="page2">
<video src="./image/532680_720p.mp4" class="video2" muted></video>
<div class="info">
<h4>放手去拍,自动成片^</h4>
<p>Vlog 拍摄配套电影级滤镜,实时更新,免费</p>
</div>
</div>
</div>
</section>
<!-- 第五屏 -->
<section class="screen section5">
<div class="rom-content">
<div class="rom-txt">
随拍风景
</div>
<div class="rom-img">
<img src="./image/chi.jpg" alt="" class="img pic1">
<img src="./image/cheng.jpg" alt="" class="img pic2">
<img src="./image/huang.jpg" alt="" class="img pic3">
<img src="./image/lv.jpg" alt="" class="img pic4">
<img src="./image/qing.jpg" alt="" class="img pic5">
<img src="./image/lan.jpg" alt="" class="img pic6">
<img src="./image/zi.jpg" alt="" class="img pic7">
</div>
</div>
</section>
<!-- js 部分 -->
<script src="./js/gsap.min.js"></script>
<script src="./js/ScrollTrigger.min.js"></script>
<script src="./js/index.js"></script>
</body>
</html>
index.js
// 第一屏幕图片滚动
ScrollTrigger.create({
trigger: ".section1",
start: "top top",
end: "+=1000",
scrub: true,
animation:
// 第一屏幕的图片由大变小
gsap
.timeline()
.fromTo(".kv-content", { scale: 1 }, { scale: 0.5 })
// 第二屏幕的视频由小变大
.fromTo(
".summary-content",
{ width: "50%", height: "50%" },
{ width: "100%", height: "100%" },
"<"
),
});
// 第二屏幕图片滚动
ScrollTrigger.create({
trigger: ".section2",
start: "top top",
end: "+=5000",
scrub: true,
// 固定屏幕
pin: true,
// 滚动滚动条的时候,自动播放视频
// 视频播放的进度和滚动条的距离连接在一起
// ScrollTrigger 的进度更改(意味着滚动位置更改)时都会调用的回调
onUpdate(self) {
const summary = document.querySelector(".summary");
try {
// 视频的播放进度随滚动条而变化
// self.progress 整体进度 0~1
// summary.duration 视频的总时长
summary.currentTime = self.progress * summary.duration;
} catch (error) {
console.log(error);
}
},
// 文字1 显示 top:20rem 看得见,然后在 top:0 看不见
// 文字2 显示 top:27rem 看得见,然后在 top:24rem 看不见
animation: gsap
.timeline()
.to(".text1", { top: "20rem", opacity: 1 })
.to(".text1", { top: 0, opacity: 0 })
.to(".text2", { top: "27rem", opacity: 1 })
.to(".text2", { top: "24rem", opacity: 0 }),
});
// 第三屏幕图片滚动
ScrollTrigger.create({
trigger: ".section3",
start: "top top",
end: "+=1000",
pin: true,
});
ScrollTrigger.create({
trigger: ".color-img",
start: "top-=500 top",
end: "+=3000",
scrub: true,
animation: gsap
.timeline()
.fromTo(
".color1",
{ "margin-left": "90em", opacity: 0 },
{ "margin-left": 0, opacity: 1 },
"<"
)
.fromTo(
".color2",
{ "margin-left": "100em", scale: 1.3 },
{ "margin-left": "10em", scale: 1 },
"<"
)
.fromTo(
".color3",
{ "margin-left": "110em", scale: 1.6 },
{ "margin-left": "20em", scale: 1 },
"<"
)
.fromTo(
".color4",
{ "margin-left": "120em", scale: 1.9 },
{ "margin-left": "30em", scale: 1 },
"<"
)
.fromTo(
".color1",
{ "margin-left": 0, opacity: 1 },
{ "margin-left": "-120em", opacity: 1 },
">"
)
.fromTo(
".color2",
{ "margin-left": "10em", scale: 1 },
{ "margin-left": "-110em", scale: 1.3 },
"<"
)
.fromTo(
".color3",
{ "margin-left": "20em", scale: 1 },
{ "margin-left": "-100em", scale: 1.6 },
"<"
)
.fromTo(
".color4",
{ "margin-left": "30em", scale: 1 },
{ "margin-left": "-90em", scale: 1.9 },
"<"
),
});
// 第四屏幕图片滚动
ScrollTrigger.create({
trigger: ".section4",
start: "top top",
end: "+=3000",
pin: true,
});
// 滚动到目标位置做动画
ScrollTrigger.create({
trigger: ".parallel",
start: "top top",
end: "+=3000",
scrub: true,
animation: gsap
.timeline()
.fromTo(".title", { opacity: 1 }, { opacity: 0 }, "<")
// page1 里面的视频动画
.fromTo(
".video1",
{ "margin-top": "100%" },
{
"margin-top": "-17%",
onStart() {
// onStart: 在动画开始时调用
const video1 = document.querySelector(".page1 .video1");
video1.currentTime = 0;
video1.play();
},
},
"<"
)
.fromTo(".info", { opacity: 0 }, { opacity: 1 })
.fromTo(".page1", { left: 0 }, { left: "-128em" }, ">")
.fromTo(
".page2",
{ left: "128em" },
{
left: 0,
onStart() {
// onStart: 在动画开始时调用
const video1 = document.querySelector(".page2 .video2");
video1.currentTime = 0;
video1.play();
},
},
"<"
),
});
// 第五屏幕图片滚动
ScrollTrigger.create({
trigger: ".section5",
start: "top top",
end: "+=3000",
pin: true,
});
ScrollTrigger.create({
trigger: ".rom-content",
start: "top+=500 top",
end: "+=2000",
scrub: true,
animation: gsap
.timeline()
.fromTo(
".rom-txt",
{ opacity: 1, "margin-top": 0 },
{ opacity: 0, "margin-top": "-7em" }
)
.fromTo(
".pic4",
{ scale: 1.8, opacity: 0, right: "63.35em", "z-index": 1 },
{ opacity: 1, right: "14.3em", "z-index": 999 },
"<"
)
.fromTo(
".pic1",
{ scale: 1.2, opacity: 0, left: "63.35em" },
{ opacity: 1, left: "23.55em" },
"<"
)
.fromTo(
".pic7",
{ scale: 1.6, opacity: 0, left: "63.35em" },
{ opacity: 1, left: "77.65em" },
"<"
)
.fromTo(
".pic2",
{ scale: 1.4, opacity: 0, left: "63.35em" },
{ opacity: 1, left: "37.25em" },
"<"
)
.fromTo(
".pic6",
{ scale: 1.4, opacity: 0, left: "63.35em" },
{ opacity: 1, left: "89.45em" },
"<"
)
.fromTo(
".pic3",
{ scale: 1.6, opacity: 0, left: "63.35em" },
{ opacity: 1, left: "50.05em" },
"<"
)
.fromTo(
".pic5",
{ scale: 1.2, opacity: 0, left: "63.35em" },
{ opacity: 1, left: "103.15em" },
"<"
),
});
index.css
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 0.78125vw !important;
overflow-x: hidden;
}
body {
/* height: 50000px; */
background-color: #000;
}
.screen {
position: relative;
width: 100%;
height: 100vh;
}
::-webkit-scrollbar{
display:none;
}
/* 第一屏css */
.kv-content {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100vh;
}
.kv-content img {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
/* 第二屏css */
.summary-content {
position: absolute;
top: 0;
left: 50%;
width: 100%;
height: 100%;
transform: translate(-50%, 0);
}
.summary-content video {
width: 100%;
height: 100%;
object-fit: cover;
}
.text1 {
position: absolute;
top: 60rem;
left: 21rem;
opacity: 0;
font-size: 4rem;
color: #fff;
}
.text2 {
position: absolute;
top: 29.266666rem;
left: 20rem;
opacity: 0;
font-size: 6rem;
color: #fff;
}
/* 第三屏 */
.color-img {
width: 49em;
position: absolute;
top: 12em;
left: 40em;
margin-top: 100px;
}
.color-img img {
width: 16em;
height: 30em;
}
.color1 {
width: 100%;
position: absolute;
top: 0;
left: 0;
margin-left: 90em;
}
.color2 {
width: 100%;
position: absolute;
top: 0;
left: 0;
margin-left: 100em;
scale: 1.1;
}
.color3 {
width: 100%;
position: absolute;
top: 0;
left: 0;
margin-left: 110em;
scale: 1.2;
}
.color4 {
width: 100%;
position: absolute;
top: 0;
left: 0;
margin-left: 120em;
scale: 1.3;
}
/* 第四屏 */
.parallel {
width: 100%;
height: 100%;
margin-top: 0;
position: relative;
overflow: hidden;
z-index: 50;
box-sizing: border-box;
}
.page1 {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.page1 .title {
width: 100%;
text-align: center;
background-clip: text;
background: -webkit-linear-gradient(left, #08f620, #fff, #00c9ff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-size: 8em;
color: #000;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.page1 .video1 {
width: 24.3em;
position: absolute;
left: 40em;
top: 50%;
transform: translate(-50%);
}
.page1 .info {
position: absolute;
left: 80em;
top: 50%;
transform: translate(-50%);
color: #fff;
}
.page2 {
display: flex;
position: absolute;
top: 0;
left: 0;
width: 128em;
height: 100%;
}
.page2 .video2 {
width: 80em;
position: absolute;
left: 50em;
top: 50%;
transform: translate(-50%, -50%);
}
.page2 .info {
position: absolute;
left: 105em;
top: 50%;
transform: translate(-50%);
color: #fff;
}
/* 第五屏 */
.rom-content {
width: 100%;
height: 100%;
position: relative;
}
.rom-txt {
width: 100%;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
font-size: 20em;
text-align: center;
background-clip: text;
background: -webkit-linear-gradient(left, #08f620, #fff, #00c9ff);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
.rom-img .img{
width: 16em;
height: 30em;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%,-50%);
}
结束
“希君生羽翼,一化北溟鱼。”