滾動視差讓你不相信「眼見為實」

2021-02-13 前端森林

引言

視差滾動(Parallax Scrolling)是指讓多層背景以不同的速度移動,形成立體的運動效果。

其實,這項技術早在 2013 年就已經開始在一些國外的網站中得到了大量的應用。由於它給網站帶來了非常出色的視覺體驗,現在已經有數不勝數的網站應用了這項技術。

我是在最近的項目中用到了這塊,覺得有必要整理一下。本文主要是簡單的介紹一下什麼是視差滾動,實現方式以及如何在現有框架(vue/react)中使用視差滾動。

什麼是視差滾動?

視差效果, 最初是一個天文術語。當我們看著繁星點點的天空時,較遠的恆星運動較慢,而較近的恆星運動較快。當我們坐在車裡看著窗外時,我們會有相同的感覺。遠處的山脈似乎沒有動,附近的稻田很快過去了。許多遊戲使用視差效果來增加場景的三維度。說的簡單點就是,滾動屏幕時,網頁中元素的位置會發生變化。但是不同的元素位置變化的速度不同,導致網頁中產生分層元素的錯覺。

看完上面這段,相信你對視差滾動的概念已經有了一個初步的了解。下面讓我們先來看一下如何用 css 來實現視差滾動。

css 實現

css 中主要有兩種實現方式:分別是通過background-attachment: fixed和transform: translate3d來實現,下面讓我們看一下具體的實現方式:

background-attachment: fixed

平時業務開發中可能不太會用到background-attachment,讓我們先來認識一下它。

background-attachment CSS 屬性決定背景圖像的位置是在視口內固定,還是隨著包含它的區塊滾動。

它一共有三個屬性:

fixed: 鍵字表示背景相對於視口固定。即使一個元素擁有滾動機制,背景也不會隨著元素的內容滾動。local: 此關鍵字表示背景相對於元素的內容固定。如果一個元素擁有滾動機制,背景將會隨著元素的內容滾動。scroll: 此關鍵字表示背景相對於元素本身固定, 而不是隨著它的內容滾動。我們使用 background-attachment: fixed 來實現視差滾動,看一下示例:
// html
<div class="a-text">1</div>
<div class="a-img1">2</div>
<div class="a-text">3</div>
<div class="a-img2">4</div>
<div class="a-text">5</div>
<div class="a-img3">6</div>
<div class="a-text">7</div>

// css
$img1: 'https://images.pexels.com/photos/1097491/pexels-photo-1097491.jpeg';

$img2: 'https://images.pexels.com/photos/2437299/pexels-photo-2437299.jpeg';

$img3: 'https://images.pexels.com/photos/1005417/pexels-photo-1005417.jpeg';

div {
height: 100vh;
background: rgba(0, 0, 0, .7);
color: #fff;
line-height: 100vh;
text-align: center;
font-size: 20vh;
}

.a-img1 {
background-image: url($img1);
background-attachment: fixed;
background-size: cover;
background-position: center center;
}

.a-img2 {
background-image: url($img2);
background-attachment: fixed;
background-size: cover;
background-position: center center;
}

.a-img3 {
background-image: url($img3);
background-attachment: fixed;
background-size: cover;
background-position: center center;
}

效果如下:

當然,你可以直接去這裡查看:https://codepen.io/jack-cool/pen/MWYogYQ

transform: translate3d

同樣,讓我們先來看一下兩個概念transform和perspective

transform: css3 屬性,可以對元素進行變換(2d/3d),包括平移 translate,旋轉 rotate,縮放 scale,等等perspective: css3 屬性,當元素涉及 3d 變換時,perspective 可以定義我們眼睛看到的 3d 立體效果,即空間感。

先來看一下示例:

// html
<div id="app">
<div class="one">one</div>
<div class="two">two</div>
<div class="three">three</div>
</div>

// css
html {
overflow: hidden;
height: 100%
}

body {
perspective: 1px;
transform-style: preserve-3d;
height: 100%;
overflow-y: scroll;
overflow-x: hidden;
}
#app{
width: 100vw;
height:200vh;
background:skyblue;
padding-top:100px;
}
.one{
width:500px;
height:200px;
background:#409eff;
transform: translateZ(0px);
margin-bottom: 50px;
}
.two{
width:500px;
height:200px;
background:#67c23a;
transform: translateZ(-1px);
margin-bottom: 150px;
}
.three{
width:500px;
height:200px;
background:#e6a23c;
transform: translateZ(-2px);
margin-bottom: 150px;
}

效果如下:

當然,你可以直接去這裡查看:https://codepen.io/jack-cool/pen/zYxzOpb

這裡解釋下使用transform: translate3d來實現視差滾動的原理:

1、給容器設置上transform-style: preserve-3d和perspective: xpx,那麼處於這個容器下的子元素就會處於 3D 空間中;

2、給子元素分別設置不同的transform: translateZ(),這時不同子元素在 3D Z 軸方向距離屏幕的距離也就不一樣;

3、滾動滾動條,由於子元素設置了不同的transform: translateZ(),那麼他們滾動的上下距離translateY相對屏幕(我們的眼睛),也是不一樣的,這就達到了滾動視差的效果。

總結下來就是: 父容器設置transform-style: preserve-3d和perspective: xpx,子元素設置不同的transform: translateZ()

看完了用 css 實現滾動視差的兩種方式,下面讓我們看下如何在現有框架(vue/react)中來應用滾動視差。

vue 或 react 中使用react 中使用

在 react 中使用可以採用react-parallax,代碼示例:

import React from "react";
import { render } from "react-dom";
import { Parallax } from "react-parallax";
import Introduction from "./Introduction";

const styles = {
fontFamily: "sans-serif",
textAlign: "center"
};
const insideStyles = {
background: "white",
padding: 20,
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%,-50%)"
};
const image1 =
"https://images.pexels.com/photos/830891/pexels-photo-830891.jpeg";
const image2 =
"https://images.pexels.com/photos/1236701/pexels-photo-1236701.jpeg";
const image3 =
"https://images.pexels.com/photos/3210189/pexels-photo-3210189.jpeg";
const image4 =
"https://images.pexels.com/photos/2437299/pexels-photo-2437299.jpeg";

const App = () => (
<div style={styles}>
<Introduction name="React Parallax" />
<Parallax bgImage={image1} strength={500}>
<div style={{ height: 500 }}>
<div style={insideStyles}>HTML inside the parallax</div>
</div>
</Parallax>
<h1>| | |</h1>
<Parallax bgImage={image3} blur={{ min: -1, max: 3 }}>
<div style={{ height: 500 }}>
<div style={insideStyles}>Dynamic Blur</div>
</div>
</Parallax>
<h1>| | |</h1>
<Parallax bgImage={image2} strength={-100}>
<div style={{ height: 500 }}>
<div style={insideStyles}>Reverse direction</div>
</div>
</Parallax>
<h1>| | |</h1>
<Parallax
bgImage={image4}
strength={200}
renderLayer={percentage => (
<div>
<div
style={{
position: "absolute",
background: `rgba(255, 125, 0, ${percentage * 1})`,
left: "50%",
top: "50%",
borderRadius: "50%",
transform: "translate(-50%,-50%)",
width: percentage * 500,
height: percentage * 500
}}
/>
</div>
)}
>
<div style={{ height: 500 }}>
<div style={insideStyles}>renderProp</div>
</div>
</Parallax>
<div style={{ height: 500 }} />
<h2>{"\u2728"}</h2>
</div>
);

render(<App />, document.getElementById("root"));

效果如下:

當然,更多細節可以查看:https://codesandbox.io/s/react-parallax-zw5go

vue 中使用

在 vue 中使用可以採用vue-parallaxy,代碼示例:

<template>
<div id="app">
<div style="background-color: #fff; height: 100vh;">
<h1 style="margin-top: 0; padding-top: 20px;">Scroll down ⬇</h1>
</div>
<div style="position: relative; z-index: 9999; background-color: #fff;">
<h1 style="margin:0;">Parallax Effect</h1>
<parallax>
<img src="https://images.pexels.com/photos/830891/pexels-photo-830891.jpeg">
</parallax>
</div>
<div style="background-color: #fff; height: 100vh;"></div>
<h1>Parallax fixed position</h1>

<div style="position: relative;">
<parallax :fixed="true">
<img src="https://images.pexels.com/photos/3210189/pexels-photo-3210189.jpeg">
</parallax>
</div>

<div style="background-color: #fff; height: 100vh;"></div>
</div>
</template>

<script>
import Parallax from "vue-parallaxy";

export default {
name: "App",
components: {
Parallax
}
};
</script>

<style>
body {
margin: 0;
}
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
position: relative;
}
</style>

效果如下:

當然,更多細節可以查看: https://codesandbox.io/s/vue-parallaxjs-ljh9g

相關焦點

  • 科學小實驗|視覺錯覺,看了這些你還相信「眼見為實」嗎?
    喬治,你相信自己的眼睛嗎? 那我告訴你,有時候眼睛也會騙人呦,可能會產生視覺錯覺。 聽起來很有意思,不如我們來研究一下吧!
  • 「眼見為實」用英語怎麼說?
    大家好,今天我們那分享一個非常有用且地道的表達——眼見為實,它的英文表達是:seeing is believing 眼見為實;百聞不如一見I never thought Mark would get out
  • 俗話說:「 耳聽為虛,眼見為實。」孔子:眼見也不一定為實!
    俗話說:「 耳聽為虛,眼見為實。」孔子:眼見也不一定為實!有句常用俗語,叫「耳聽為虛,眼見為實」,是形容不要輕信傳聞,看到的才是事實。聽來的傳聞是靠不住的,親眼看到才算是真實的。是謂親眼看見的比聽說的要真實可靠。
  • 眼見為實?科學研究顛覆你的常識!
    眼見為實,然而,為什麼人類往往看到的都是假象呢?中國有句古話:「耳聽為虛,眼見為實」。聽來的傳聞是靠不住的,親眼看到才算是真實的。親眼看見的比聽說的要真實可靠。聽別人講和自己看到是不同的,看到的可以是真實情況,而聽人講往往是虛假的,道聽途說,沒有親眼所見就不要相信。
  • 不要相信你的眼睛:那些和《紀念碑谷》相似的視差遊戲盤點
    這款由First Sight Games開發的解謎遊戲巧妙地利用了人的視差錯覺,為玩家們構建了一座座看起來不可思議的迷宮。 錯覺圖形大師M.C.Escher和他的作品 不過無論再好的遊戲終究是要通關的,當你放下手機
  • 「視差」和星盤解讀【Astrology News】
    當兩位觀察者身處不同方位觀察同一物體時,視差便產生了。舉一個在日常生活中常見的例子,帶你理解究竟何為「視差」。 測量視差:物體距離兩個人越近,兩條視線相交的角度也就越大。這個角度可以用作測量視差。當物體被放得越來越遠,視差也會無限趨近於零。需要注意的是,這種視差取決於兩點:兩位觀察者彼此相距的距離,以及被觀察物體與他們的距離。
  • 注視視差檢查法
    有數個臨床檢測法可用來評估這個注視視差量如:Mallett遠點測量裝置(Mallett unit)、美國光學偏振立體幻燈圖(American Opticalvectographic slide)、Bermell燈式遠點視標(Bernell lantern slide)、Wesson注視視差卡(Wesson card)、Sheedy注視視差測量儀(Sheedy Disparometer)。
  • 基於MAP-MRF的視差估計
    日益增長的數據量,同時內部數據還受到諸如光照變化、遮擋等不可控環境因素的影響都對深度圖估計的效率、精度都提出了挑戰。參考影像的深度估計可以轉化為立體像對的視差估計,傳統方法利用稠密匹配的算法進行快速特徵匹配,例如半全局匹配算法,而往往在收到遮擋的影響而效果不佳。而深度學習方法在立體視覺中的成功應用,使得高效率、高精度的基於神經網絡的端到端三維重建成為可能。
  • 俗話說:耳聽為虛,眼見為實,眼見就一定為實嗎?
    《漫談漢字語言詩詞曲賦經典文化》系列之俗語文化第4回俗話說:「 耳聽為虛,眼見為實。」眼睛看到的就一定真實嗎?原以為年齡越來越大,萬物好像會更清晰,事實是越來越模稜兩可。發現眼睛也會騙人,蒙蔽事實真相。今天小編就和大家一起聊聊關於「耳聽為虛,眼見為實」的話題。
  • 耳聽為虛,眼見為實也不一定是真哦!
    你說的我聽見,你做的我看見。但是因為我知道你是什麼職業的,因為你所展現的外在條件,就直接把你歸類了。就好像看到開豪車的人就以為他是有錢人,但卻不曾想過,那車有可能是分期的二手車,還可能有數額巨大的外債。看見騎共享單車的就不會把他與有錢人畫等號。
  • 眼見為實,耳聽為虛,是否真的可以作為事實的判斷依據
    人們常說,眼見為實,耳聽為虛。這句話常常作為人們判斷事實的依據,耳朵傳來的信息總有點不大確定,一定要親眼看到才相信。的確如此,人們常常聽到謠言,如果不加以判斷,偏聽偏信,那麼造成的後果是不堪設想的,輕則損財,重則害命。
  • 意想不到,三角形照樣滾動!
    如果你問一個小孩子什麼形狀可以滾動,相信小孩子會不假思索的告訴你是圓形。在我們的世界中能滾動的東西都是圓的,各種類型的球,車輪,電池,水杯,原木,水桶等等。那麼我們有沒有想過三角形可以滾動嗎?提出這個問題肯定很多人會不屑的回答三角形肯定走不動。
  • 揭秘:眼見為實可能不是真相,生活中我們能看見的大多是假象
    盒子內的貓是死亡還是活著,決於觀察者的觀察角度、觀察時間、觀察空間等觀察條件,其所有的觀察結果其實是這隻貓在不同時空呈現的不同實像,而不一定就是貓的真實狀態。這就個實驗證明了人類對萬物眼見為實的觀察結果,其實是該物體在某時空點展示出的一種量子糾纏狀態,而不一定是物體的真相。
  • 眼見為實這種事,以前是也許是對的,但看完這些圖之後也許是錯的
    眼見為實這種事,以前是也許很多人都認為這是對的,因為只有當你親眼看過之後你才會相信事實的真相。但看完下面這些圖之後也許是「眼見為實」往往是錯的,因為你看到的根本就不是事實,事實的真相也並不是你所看到的那樣。這些都是因為有一個東西在作怪,那就是:錯覺。視覺上的錯覺,控制著你眼睛所看到的和你的大腦所感知到的之間的轉換。
  • 「周年視差」這個原理非常簡單,但是在觀測天體上有很多的困難
    舉例說明:伸出手臂豎起你的手指,分別閉上你的左眼和右眼,這時候你會看到你的手指在背景上是處於不同位置的,然後把你的手臂往胸前彎曲,分別再閉上你的左眼和右眼,你會看到你的手指指在背景上的位置是不一樣的「周年視差」,在周年視差裡面視差角的大小是由恆星相對於日地距離所張的角度,測量了日地的距離再得到視差的大小,就可以得到天體到底離我們有多遠。
  • 眼見為實!?蜘蛛俠現身說法:你看到的不一定都是真的
    在這個全民都可成為自媒體,都可擔任影片剪接的年代,「眼見為實」變成非常不安全的準則。在我們這些看完電影的現實觀眾眼中真相是清晰的,但那些身在局中漫威電影宇宙的紐約市民的眼中,看到的卻是赤裸裸的「真相」,神秘客正是利用這一點,偽造了一段看似真實的「蜘蛛俠謀殺神秘客」視頻。《蜘蛛俠:英雄遠徵》由導演喬·沃茨再次執導,「蜘蛛俠」湯姆·赫蘭德、「局長」塞繆爾·傑克遜重磅加盟!
  • 眼見為實?但,人的眼睛是很容易受騙的,不信看看?
    實際上,人的眼睛是很容易受騙的,「眼見為實」遠不是一種嚴謹的說法,北岡明佳為證實這一點,此前曾發布過不少這樣的內容比如這張圖,你會感覺圖片中間在發光。你會感覺圖片是凸出的,而實際上所有方塊都是正方形所以,在有些情況下,不要太過於相信自己的眼睛了!
  • 為什麼滾動真空包裝機漏氣
    真空包裝是為了除氧,滾動真空包裝機是可以連續性工作的除氧工作,即它是真空減壓包裝的一種。目前食品廠、工業原料廠、電子廠等不少都會用到真空包裝機,它們應用的目的各不相同,延時食品的保質期、保鮮期,防止原料氧化,防止電子元件生鏽等。
  • 從窗戶看宇宙︱用3分鐘解讀3視差法
    最後,經過考慮,小編選擇了一個大家都比較感興趣,背後原理又較為簡單的話題,那就是三角視差法在我們的日常生活中,如果我們要測量兩個物體之間的距離,直尺、米尺和皮尺都是非常實用的工具。但是如果我們想要簡單而精準地測量兩個物體間的距離,這些工具可能就有點小兒科了,於是三角視差法登場了。
  • NASA新視野號飛船正式進行了首次星際視差實驗
    本文轉自【cnBeta.COM】;美國宇航局(NASA)的 "新視野 "號宇宙飛船正式進行了首次星際視差實驗。美國宇航局表示,這是太空飛行器首次從如此遙遠的地方將天空的圖像傳回地球,以至於恆星看起來與我們從地球上看到的位置不同。新視野號目前距離地球40億英裡,正朝著星際空間前進。