滚动视差!马萨卡?!!!

lxf2023-03-17 18:14:01

最简单的代码,最极致的享受,主打的就是一个炫酷~

滚动视差

滚动视差效果(Parallax Scrolling)是指让多层背景以不同的速度位移,形成立体的运动效果的视觉体验,在前端强交互的时代,更应该多考虑这种用户体验较好的动效~

实现方案

  1. JS监听浏览器 scroll 事件,不断改变元素位置
  2. background-attachment属性,将图片位置相对于视口固定
  3. translateZ()修改元素的缩小比例,使得滚动速度出现差异

JS实现

// html
<div class="parallax">
  <img src="./images/bc1.png" id="bc1" />
  <img src="./images/bc2.png" id="bc2" />
  <img src="./images/bc3.png" id="bc3" />
  <img src="./images/bc4.png" id="bc4" />
  <img src="./images/bc5.png" id="bc5" />
  <img src="./images/tree.png" id="tree" />
  <h2 id="text">Rolling Parallax</h2>
  <img src="./images/leaf.png" id="leaf" />
  <img src="./images/plant.png" id="plant" />
</div>

<div class="contentBox">
  <h2>Parallax Scrolling</h2>
  <text class="content">
    content...
  </text>
</div>

//css
@import url("https://fonts.googleapis.com/css?family=Luckiest+Guy");

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: "Luckiest Guy", cursive;
}
body {
  background: #f9f9f9;
  min-height: 100vh;
  overflow-x: hidden;
}
.parallax {
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}
.parallax img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  pointer-events: none;
}
#text {
  position: absolute;
  font-size: 5em;
  color: #fff;
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.2);
  letter-spacing: 10px;
}
.contentBox {
  position: relative;
  background: #003329;
  padding: 100px;
}
.contentBox h2 {
  font-size: 36px;
  color: #fff;
  margin-bottom: 10px;
  letter-spacing: 2px;
}
.contentBox .content {
  font-size: 20px;
  color: #fff;
  font-weight: 300;
  line-height: 28px;
  letter-spacing: 2px;
}
//js
let text = document.getElementById("text");
let leaf = document.getElementById("leaf");
let bc1 = document.getElementById("bc1");
let bc4 = document.getElementById("bc4");
let bc5 = document.getElementById("bc5");

window.addEventListener("scroll", () => {
  const value = window.scrollY;
  text.style.marginTop = value * 1.5 + "px";
  leaf.style.top = value * -1.5 + "px";
  leaf.style.left = value * 1.5 + "px";
  bc1.style.top = value * 0.5 + "px";
  bc4.style.left = value * -1.5 + "px";
  bc5.style.left = value * 1.5 + "px";
});

预览效果如下

滚动视差!马萨卡?!!!

CSS-background-attachment

前置知识

首先 background-attachment 要和 background-image 一起使用才有意义,表示的是背景图像是否固定或者随着页面的其余部分滚动。
background-attachment 有四个可选值:fixed,scroll,local,inherit
scroll 是该属性的默认值,表示背景图相对于元素固定,简单理解就是两者绑定住了,所以元素滚动了图片也会跟着滚动。
local 表示背景图相对于元素内容固定,而相对于其他滚动条则会滚动。举例来说,假如元素内部设置了overflow:scroll,则元素内部会出现滚动条,此时滚动元素内部滚动条的时候,背景图会随着滚动而滚动。而如果我们设置 background-attachment:scroll ,则背景图会随着元素内部滚动而固定住。
fixed 表示背景图相对于视口固定,无论怎么滚动,元素都岿然不动,如果多个元素都设置了fixed,他们也只会在自己的元素内显示,互不影响。
inherit 只是指定 background-attachment 的设置从父元素继承。

scroll与local的区别

scroll效果如下 滚动视差!马萨卡?!!! local效果如下 滚动视差!马萨卡?!!!

//html
<div class="image_1">
  <div class="word">Bye bye, Lucia</div>
</div>
<div class="bg">The best hard are always the bravest</div>
<div class="image_2">
  <div class="word">All children, except one, grow up</div>
</div>
<div class="bg">It's better to burn out than to fade away</div>
<div class="image_3">
  <div class="word">Fading is true while flowering is past</div>
</div>
<div class="bg">There was no possibility of taking a walk</div>
<div class="image_4">
  <div class="word">All this happened, more or less</div>
</div>

//css
* {
  padding: 0;
  margin: 0;
}
.image_1 {
  background-image: url(./images/1.webp);
  background-position: 0 0;
  background-attachment: fixed;
  background-size: cover;
  height: 680px;
  width: 100%;
}
.image_2 {
  background-image: url(./images/2.jpg);
  background-position: 0 0;
  background-attachment: fixed;
  background-size: cover;
  height: 680px;
  width: 100%;
}
.image_3 {
  background-image: url(./images/3.jpg);
  background-position: 0 0;
  background-attachment: fixed;
  background-size: cover;
  height: 680px;
  width: 100%;
}
.image_4 {
  background-image: url(./images/4.jpeg);
  background-position: 0 0;
  background-attachment: fixed;
  background-size: cover;
  height: 680px;
  width: 100%;
}
.word {
  position: relative;
  top: 480px;
  font-size: 55px;
  color: white;
  text-align: center;
  font-weight: bolder;
}
.bg {
  text-align: center;
  font-size: 46px;
  font-weight: bolder;
  height: 220px;
  line-height: 220px;
  background-color: rgb(131, 134, 204);
  color: white;
}

预览效果如下

滚动视差!马萨卡?!!!

CSS-translateZ

前置知识

transform-style: preserve-3d表示让子元素保留3D转换。

滚动视差!马萨卡?!!!

好吧,直接上图上代码~

//html
<div class="wrapper">
  <div class="demo"></div>
</div>

//css
body {
  perspective: 800px;
  perspective-origin: 250px 300px;
}
.wrapper {
  position: relative;
  left: 200px;
  top: 100px;
  height: 480px;
  width: 60%;
  background-color: #0ff;
  transform: rotateY(45deg);
  /* transform-style: preserve-3d; */
}
.demo {
  height: 100%;
  background-image: url(./images/3.jpg);
  background-size: cover;
  transform: translateZ(100px);
}

不加preserve-3d效果

滚动视差!马萨卡?!!!

加上preserve-3d效果

滚动视差!马萨卡?!!!

看出差异了吧,有层次了,立体感高高的~
需要注意的是 transform-style: preserve-3d 这个属性加在谁身上,谁的子元素才会有3D效果,比如上面的代码中把属性加在 body 上是没有效果的。

perspective 定义3D元素距视图的距离。

简单来理解,如果我设置了 perspective:500px,则表示我在离屏幕500px远的地方观看这个元素。注意一下官方讲解的 当为元素定义 perspective 属性时,其子元素会获得透视效果,所以我们需要将这个属性设置在父元素上。

加上perspective效果

滚动视差!马萨卡?!!!

不加perspective效果

滚动视差!马萨卡?!!!

视距 = 距离产生美~

translateZ: 向Z轴平移。

我们现在和屏幕的距离就是Z轴,所以Z轴是朝向我们的,如果translateZ里面的值越大,说明屏幕离我们越近,translateZ里面的值越小,屏幕离我们就越远。

perspective和translateZ的化学反应

这两者有什么区别呢,简单的说就是translateZ是移动图片,perspective是移动人和屏幕的距离。但是当这两者结合起来的时候神奇的事情就会发生~

//html
<div class="wrapper">
  <div class="demo"></div>
</div>

//css
.wrapper {
  position: relative;
  left: 200px;
  top: 100px;
  height: 480px;
  width: 60%;
  perspective: 800px;
}
.demo {
  height: 100%;
  background-image: url(./images/3.jpg);
  background-size: cover;
  transform: translateZ(-100px);
}

perspective: 800px的情况

滚动视差!马萨卡?!!!

perspective: 100px的情况

滚动视差!马萨卡?!!!

我们把视距调小,图片竟然变小了,按照道理视距越小说明屏幕离我越近,图片应该变大才对。其实,这里我们看到的图片,并不是图片本体,而是图片在屏幕上的投影。

滚动视差!马萨卡?!!!

同理,我们去理解translateZ的值变大,图片变大也比较容易了。

translateZ(-100px)的情况

滚动视差!马萨卡?!!!

translateZ(-20px)的情况

滚动视差!马萨卡?!!!

滚动视差!马萨卡?!!!

那么只要我们将不同的元素的translateZ设置成不同的负值,那么越大值的元素,它的投影就会越大,滚动速度就会越快,当然这些元素的滚动速度也只有translateZ(0)的几分之一~

//html
<div class="g-container">
  <div class="section-one">translateZ(-1)</div>
  <div class="section-two">translateZ(-2)</div>
  <div class="section-three">translateZ(-3)</div>
</div>

//css
html {
  height: 100%;
  overflow: hidden;
}
body {
  margin: 0;
  padding: 0;
  height: 100%;
  overflow-y: scroll;
  overflow-x: hidden;
  perspective: 2px;
}
.g-container {
  position: relative;
  transform-style: preserve-3d;
  transform-origin: center center;
  height: 150%;
}
.g-container div {
  font-size: 5vw;
  position: absolute;
  top: 20%;
}
.section-one {
  left: 0%;
  background: rgba(10, 10, 10, 0.2);
  transform: translateZ(-1px);
}
.section-two {
  left: 40%;
  background: rgba(30, 130, 30, 0.2);
  transform: translateZ(-2px);
}
.section-three {
  left: 90%;
  background: rgba(200, 100, 130, 0.2);
  transform: translateZ(-3px);
}

预览效果如下

滚动视差!马萨卡?!!!

参考:css3系列之详解perspective:www.cnblogs.com/yanggeng/p/…