自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

一篇帶你學(xué)習(xí) CSS 實(shí)現(xiàn)卷軸滾動(dòng)效果

開(kāi)發(fā) 前端
首先 CSS? 中并沒(méi)有真正的 3d 滾動(dòng),立方體還可以勉強(qiáng)拼接,這種圓形的不行,因此我們需要用其他方式來(lái)實(shí)現(xiàn)。這里其實(shí)是一個(gè)最簡(jiǎn)單的平移動(dòng)畫(huà),只需要將紋理上下無(wú)縫平移,結(jié)合漸變和陰影,就能得到看似滾動(dòng)的效果了。

「慶余年2」 終于開(kāi)播了~最近起點(diǎn)讀書(shū)APP內(nèi)上架了慶余年典藏書(shū),最大的特色是里面新加入了全新的閱讀皮膚,一個(gè)擬物化的卷軸滾動(dòng)效果,效果如下:

圖片

就是在拖動(dòng)頁(yè)面時(shí),卷軸會(huì)隨著頁(yè)面的滾動(dòng)而展開(kāi)或卷起,就像在拖動(dòng)真的畫(huà)布一樣,非常舒適,錄屏可能看著不是很清晰,強(qiáng)烈建議去端內(nèi)自行體驗(yàn)。

當(dāng)時(shí)看到這個(gè)效果時(shí)就在思考,如何在 web 中也實(shí)現(xiàn)這樣一個(gè)效果呢?

經(jīng)過(guò)一番琢磨,發(fā)現(xiàn)僅使用 CSS 就能完成這樣的效果。下面是我復(fù)刻的效果。

圖片

這是如何實(shí)現(xiàn)呢?一起看看吧

一、CSS卷軸滾動(dòng)的原理

首先 CSS 中并沒(méi)有真正的 3d 滾動(dòng),立方體還可以勉強(qiáng)拼接,這種圓形的不行,因此我們需要用其他方式來(lái)實(shí)現(xiàn)。

這里其實(shí)是一個(gè)最簡(jiǎn)單的平移動(dòng)畫(huà),只需要將紋理上下無(wú)縫平移,結(jié)合漸變和陰影,就能得到看似滾動(dòng)的效果了。

先簡(jiǎn)單布局一下。

<div class="reel">
  <div class="reel-bg"></div>
</div>

這里要用到卷軸的素材圖片,是這樣的。

兩邊保留,中間拉伸的一個(gè)自適應(yīng)結(jié)構(gòu),可以用到border-image,劃分出需要拉伸的地方即可。

有關(guān)border-image的詳細(xì)教程可以自行搜索,這里就不展開(kāi)了,具體實(shí)現(xiàn)如下:

.reel{
  position: relative;
  height: 28px;
  margin: 0 15px;
  border-image: url("卷軸.png") fill 42 36/14px 12px/0 12px;
}

這樣就能得到卷軸的結(jié)構(gòu)了。

接下來(lái)就是紋理了,素材是這個(gè)。

我們把這個(gè)素材放在卷軸容器了,做上下無(wú)限平移動(dòng)畫(huà)。

.reel-bg{
  position: absolute;
  left: 0;
  width: 100%;
  height: 368px;
  background: url("紋理.jpg") 50% 0/auto 50%;
	animation: scroll 3s linear forwards infinite;
}
@keyframes scroll {
  0%{
    transform: translateY(-50%);
  }
  100% {
    transform: translateY(-0%);
  }
}

效果如下:

現(xiàn)在看著非常扁平,沒(méi)有立體感,主要是紋理沒(méi)有融入到背景之中。

如何將紋理完美的融合到后面的背景呢?沒(méi)錯(cuò),需要用到混合模式,這里用正片疊底就行了。

.reel-bg{
  /**/
  mix-blend-mode: multiply;
}

效果就好很多了。

最后給卷軸加點(diǎn)陰影,超出隱藏。

.reel{
  /**/
  overflow: hidden;
  box-shadow: 0 5px 10px 5px rgba(0,0,0,.3), 0 10px 20px 10px rgba(0,0,0,.5);
}

這樣就比較真實(shí)了。

滾動(dòng)效果出來(lái)了,如何和頁(yè)面滾動(dòng)關(guān)聯(lián)起來(lái)呢?接著往下看。

二、CSS滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)

回到這里,先把整個(gè)布局完善一下。

<body>
  <div class="reel">
    <div class="reel-bg"></div>
  </div>
  <article>
    <p>范慎很困難地?fù)沃涎燮?,看著指頭算自己這輩子做過(guò)些什么有意義的事情,結(jié)果右手五根瘦成筷子一樣的指頭還沒(méi)有數(shù)完,他就嘆了一口氣,很傷心地放棄了這個(gè)工作。病房里的藥水味總是這么刺鼻,旁邊那床的老爺子前兩天已經(jīng)去地藏王菩薩那里報(bào)道了,大概再過(guò)幾天就輪到自己吧。他得了某種怪病,重癥肌無(wú)力,就是特別適合言情小說(shuō)男主角的那種病。據(jù)說(shuō)沒(méi)得醫(yī),將來(lái)嗝屁的那天什么都動(dòng)不了,只有眼淚可以流下來(lái)。痛!</p>
    <p>范慎很困難地?fù)沃涎燮?,看著指頭算自己這輩子做過(guò)些什么有意義的事情,結(jié)果右手五根瘦成筷子一樣的指頭還沒(méi)有數(shù)完,他就嘆了一口氣,很傷心地放棄了這個(gè)工作。病房里的藥水味總是這么刺鼻,旁邊那床的老爺子前兩天已經(jīng)去地藏王菩薩那里報(bào)道了,大概再過(guò)幾天就輪到自己吧。他得了某種怪病,重癥肌無(wú)力,就是特別適合言情小說(shuō)男主角的那種病。據(jù)說(shuō)沒(méi)得醫(yī),將來(lái)嗝屁的那天什么都動(dòng)不了,只有眼淚可以流下來(lái)。痛!</p>
    <!--很多文本-->
  </article>
</body>

簡(jiǎn)單修飾一下,由于卷軸要固定到頂部,可以采用sticky布局。

html{
  background-color: #22312D;
  font-family: cursive;
}
body{
  margin: 0;
}
article{
  background-color: #F5EBD4;
  padding: 1em 0.5em;
  border-left: 10px solid #405C53;
  border-right: 10px solid #405C53;
  margin: 0 15px;
}
p{
  margin: 0;
  padding: 0.2em 0;
  color: #2C402E;
  line-height: 150%;
  text-indent: 2em;
}
h1{
  text-align: center;
  color: #F5EBD4;
}

效果如下:

不過(guò)這里還有點(diǎn)問(wèn)題,由于是整個(gè)頁(yè)面在滾動(dòng),內(nèi)容滾到頂部會(huì)漏出來(lái),如下:

所以還需要找個(gè)東西遮擋一下,這里我們直接用偽元素實(shí)現(xiàn),設(shè)置相同的背景色就行了。

html::before{
  content: '';
  display: block;
  height: 30px;
  background: inherit;
  position: sticky;
  top: 0;
}

由于是sticky,也不用關(guān)注層級(jí)問(wèn)題,效果如下:

現(xiàn)在就讓卷軸滾動(dòng)和頁(yè)面滾動(dòng)聯(lián)動(dòng)起來(lái), 非常簡(jiǎn)單,只需要添加animation-timeline屬性就行了,設(shè)置滾動(dòng)時(shí)間線為root,如下:

.reel-bg{
  animation: scroll 1s linear forwards;
  animation-timeline: scroll(root);
}

這樣在頁(yè)面滾動(dòng)時(shí)卷軸也跟著“轉(zhuǎn)動(dòng)”了。

但看著卷軸轉(zhuǎn)地是不是有點(diǎn)慢了?

確實(shí)是這樣,這個(gè)時(shí)候表示頁(yè)面從頭滾到到底部,執(zhí)行一次動(dòng)畫(huà),也就是滾動(dòng)一圈,所以頁(yè)面內(nèi)容越多,滾動(dòng)距離越長(zhǎng),那么卷軸轉(zhuǎn)的也就越慢。

下面來(lái)修復(fù)這個(gè)問(wèn)題

三、優(yōu)化卷軸滾動(dòng)速度

簡(jiǎn)單來(lái)處理,可以給個(gè)合適的動(dòng)畫(huà)次數(shù),比如:

.reel-bg{
  animation: scroll 1s linear forwards 5;
  animation-timeline: scroll(root);
}

這樣表示頁(yè)面從頭滾到到底部,會(huì)執(zhí)行5次動(dòng)畫(huà),也就是相當(dāng)于會(huì)滾動(dòng)5圈,所以看著速度就變快了。

現(xiàn)在就舒服多了。

不過(guò)這種處理方式有個(gè)問(wèn)題,動(dòng)畫(huà)次數(shù)是跟內(nèi)容長(zhǎng)度強(qiáng)相關(guān)的,如果在向下滾動(dòng)時(shí)動(dòng)態(tài)加載內(nèi)容,就需要更新這個(gè)值,稍顯麻煩。

那么,有沒(méi)有辦法讓滾動(dòng)速度保持均衡呢?也就是無(wú)論內(nèi)容多少,速度都是一致的。

這就需要用到 CSS 動(dòng)畫(huà)范圍區(qū)間了,也就是animation-range,簡(jiǎn)單來(lái)講就是設(shè)置滾動(dòng)區(qū)間。

默認(rèn)情況下,滾動(dòng)區(qū)間就是從頁(yè)面頂部滾動(dòng)到底部,我們可以手動(dòng)改變這個(gè)范圍,比如我們?cè)O(shè)置一個(gè)比較大的值。

.reel-bg{
  --s: 999999;
  animation: scroll 1s linear forwards;
  animation-timeline: scroll(root);
  animation-range: 0 calc(var(--s) * 1px);
}

這個(gè)表示頁(yè)面滾動(dòng)從0滾動(dòng)到999999px時(shí),上面的卷軸會(huì)滾動(dòng)一圈。這顯然不行,我們需要?jiǎng)討B(tài)去計(jì)算滾動(dòng)的圈數(shù),就是動(dòng)畫(huà)播放次數(shù)。

.reel-bg{
  animation-iteration-count: calc(var(--s)/184/3.14);
}

為啥是這個(gè)值呢?簡(jiǎn)單解釋一下,184是這個(gè)卷軸上下的平移距離,然后再除以圓周率3.14,這樣看著會(huì)更加自然。

這樣就能完美實(shí)現(xiàn)卷軸滾動(dòng)了,無(wú)論內(nèi)容長(zhǎng)短,滾動(dòng)速度都是一致的。

圖片

核心實(shí)現(xiàn)其實(shí)就這幾行,是不是非常簡(jiǎn)單。

.reel-bg{
  --s: 999999;
  animation: scroll 1s linear forwards calc(var(--s)/184/3.14);
  animation-timeline: scroll(root);
  animation-range: 0 calc(var(--s) * 1px);
}

四、不支持瀏覽器兼容

雖然 CSS 實(shí)現(xiàn)很簡(jiǎn)單,但是兼容性還不行,截至目前(2024年4月27日)僅支持Chrome 115+。

所以實(shí)際生成中不能直接使用,需要降級(jí)處理。

簡(jiǎn)單的降級(jí)是不支持的不執(zhí)行動(dòng)畫(huà),這個(gè)只需要用@supports查詢(xún)一下就行了。

@supports (animation-timeline: scroll()) {
  .reel-bg{
    --s: 999999;
    animation: scroll 1s linear forwards calc(var(--s)/184/3.14);
    animation-timeline: scroll(root);
    animation-range: 0 calc(var(--s) * 1px);
  }
}

這樣在不支持的瀏覽器,比如 Safari 下就不會(huì)自動(dòng)播放動(dòng)畫(huà)了。

如果也想實(shí)現(xiàn)卷軸滾動(dòng)效果,那就需要借助JS的力量,其實(shí)實(shí)現(xiàn)也不難,就是找到頁(yè)面的scrollTop和紋理的上下平移關(guān)系,做個(gè)映射就好了,具體實(shí)現(xiàn)如下:

if (!CSS.supports('animation-timeline: scroll()')){
  console.log('不支持animation-timeline')
  const bg = document.querySelector('.reel-bg')
  window.addEventListener('scroll',function(){
    console.log(this.scrollY)
    bg.style.transform = `translateY(${this.scrollY / Math.PI % 184 / 368 * 100 - 80}%)`
  })
}

下面是在Safari中的效果,也能完美支持了。

你也可以訪問(wèn)以下鏈接查看真實(shí)效果。

  • CSS QYN book (juejin.cn)[1]
  • CSS QYN book (codepen.io)[2]

五、總結(jié)一下

以上就是本文的全部?jī)?nèi)容了,一個(gè)有趣的交互效果,你學(xué)到了嗎,下面總結(jié)一下本文重點(diǎn)。

  • CSS卷軸滾動(dòng)的原理其實(shí)是一個(gè)最簡(jiǎn)單的平移動(dòng)畫(huà),只需要將紋理上下無(wú)縫平移,結(jié)合漸變和陰影,就能得到看似滾動(dòng)的效果了。
  • 簡(jiǎn)單的平移動(dòng)畫(huà)看著非常扁平,沒(méi)有立體感,主要是紋理沒(méi)有融入到背景之中。
  • 利用混合模式正片疊底,可以讓平移動(dòng)畫(huà)看著像滾動(dòng)動(dòng)畫(huà)了。
  • CSS 滾動(dòng)驅(qū)動(dòng)動(dòng)畫(huà)可以讓頁(yè)面滾動(dòng)和卷軸滾動(dòng)聯(lián)動(dòng)起來(lái)。
  • 默認(rèn)情況下,頁(yè)面從頭滾到到底部,執(zhí)行一次動(dòng)畫(huà),也就是滾動(dòng)一圈,所以頁(yè)面內(nèi)容越多,滾動(dòng)距離越長(zhǎng),卷軸轉(zhuǎn)的也就越慢。
  • 可以通過(guò)改變動(dòng)畫(huà)重復(fù)次數(shù)來(lái)調(diào)整卷軸滾動(dòng)速度,局限是需要根據(jù)頁(yè)面滾動(dòng)長(zhǎng)度來(lái)計(jì)算合適的數(shù)值。
  • 用足夠大的 CSS 動(dòng)畫(huà)范圍區(qū)間(animation-range)配合動(dòng)畫(huà)重復(fù)次數(shù)可以實(shí)現(xiàn)卷軸滾動(dòng)速度保持均衡。
  • 目前兼容性還有些差,可以用CSS.supports做兼容處理。

[1]CSS QYN book (juejin.cn): https://code.juejin.cn/pen/7362400098958966793。

[2]CSS QYN book (codepen.io): https://codepen.io/xboxyan/pen/VwNqEoE。

責(zé)任編輯:姜華 來(lái)源: 前端偵探
相關(guān)推薦

2022-03-17 19:29:04

CSS切角自適應(yīng)

2021-08-23 06:25:57

CSS 技巧animation

2021-06-16 08:28:25

unary 方法函數(shù)技術(shù)

2022-12-14 08:03:27

CSS變量前端

2022-05-05 07:40:07

maskCSS

2023-04-21 08:11:54

KubernetesPod

2021-03-26 09:57:51

SVGHtml基礎(chǔ)SVG圖像

2022-04-08 08:32:40

mobx狀態(tài)管理庫(kù)redux

2021-04-07 06:11:37

Css前端CSS定位知識(shí)

2021-01-25 05:39:54

Css前端Border

2021-05-31 09:30:36

Css前端CSS 特效

2020-11-03 19:18:28

CSS對(duì)齊文本

2020-11-17 11:10:21

CSS選擇器HTML

2021-05-20 06:57:16

RabbitMQ開(kāi)源消息

2023-04-20 08:00:00

ES搜索引擎MySQL

2021-07-13 11:37:47

cpu架構(gòu)Linux

2022-04-21 08:41:49

css前端

2021-05-20 09:02:59

CSS單位長(zhǎng)度

2023-08-01 14:34:12

HTMLCSS

2023-06-28 15:04:59

CSSHTML
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)