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

CSS 實(shí)現(xiàn)3d輪播圖的一些思路,你學(xué)會(huì)了嗎?

開(kāi)發(fā) 前端
原效果是通過(guò)vue的transition?組件實(shí)現(xiàn)的,感覺(jué)有些笨重,思考了一番,發(fā)現(xiàn)純 CSS也能實(shí)現(xiàn)這樣的效果,而且性能更好,實(shí)現(xiàn)也更簡(jiǎn)潔,一起來(lái)看看吧!
最近在項(xiàng)目中碰到一個(gè)比較典型的3d輪播圖動(dòng)效,如下所示:

圖片圖片

說(shuō)難不難,說(shuō)簡(jiǎn)單也不簡(jiǎn)單,這是一個(gè)無(wú)限循環(huán)的輪播效果,并且個(gè)數(shù)是固定的,你會(huì)如何實(shí)現(xiàn)呢?

原效果是通過(guò)vue的transition組件實(shí)現(xiàn)的,感覺(jué)有些笨重,思考了一番,發(fā)現(xiàn)純 CSS也能實(shí)現(xiàn)這樣的效果,而且性能更好,實(shí)現(xiàn)也更簡(jiǎn)潔,一起來(lái)看看吧!

一、CSS 動(dòng)畫(huà)實(shí)現(xiàn)思路

首先來(lái)分析一下思路。看著是一個(gè)連貫的輪播效果,其實(shí)單獨(dú)看每一個(gè)子項(xiàng),都是完全相同的運(yùn)動(dòng)軌跡。

圖片圖片

然后是這個(gè)動(dòng)畫(huà),其實(shí)就是6個(gè)關(guān)鍵幀,逐一去位移和縮放,如下:

圖片圖片

然后給每個(gè)子項(xiàng)不同的“負(fù)延遲”,是不是就剛好錯(cuò)開(kāi),形成一個(gè)完整的輪播效果了呢?

無(wú)論CSS怎么實(shí)現(xiàn),動(dòng)畫(huà)原理就這些了,下面來(lái)看幾個(gè)實(shí)現(xiàn)方式

二、CSS 動(dòng)畫(huà)關(guān)鍵幀

首先簡(jiǎn)單布局一下,先用一個(gè)元素實(shí)現(xiàn)動(dòng)畫(huà);

<div class="item"></div>

加點(diǎn)修飾;

html,body{
  font-family: -apple-system, "BlinkMacSystemFont", sans-serif;
  margin: 0;
  height: 100%;
  display: flex;
  justify-content: center;
  flex-direction: column;
  align-items: center;
  background: aliceblue;
  counter-reset: num;
}
.item{
  position: absolute;
  display: grid;
  place-content: center;
  width: 100px;
  height: 100px;
  border-radius: 8px;
  background-color: #3E65FF;
  color: #fff;
  font-size: 30px;
  counter-increment: num;
}

這里的數(shù)字是用CSS計(jì)數(shù)器生成的,效果如下:

圖片圖片

根據(jù)前面的關(guān)鍵幀,很容易用代碼實(shí)現(xiàn),就是。

.item{
  animation: slide 12s infinite;
}
@keyframes slide {
  0%,100% {
    transform: translate(0%, 0%) scale(1);
  }
  16.67% {
    transform: translate(120%, -30%) scale(0.9);
  }
  33.33% {
    transform: translate(100%, -70%) scale(0.8);
  }
  50% {
    transform: translate(0, -90%) scale(0.7);
  }
  66.67% {
    transform: translate(-100%, -70%) scale(0.8);
  }
  83.33% {
    transform: translate(-120%, -30%) scale(0.9);
  }
}

這里的16.67%關(guān)鍵幀是將100%進(jìn)行6等分得到的,如下所示:

圖片圖片

效果如下:

圖片圖片

雖然有動(dòng)畫(huà)了,但是效果有點(diǎn)奇怪,每次改變位置的時(shí)候好像沒(méi)有停頓,顯得過(guò)渡有些緩慢,只是有減速和加速的過(guò)程,這是默認(rèn)的ease-in-out的淡入淡出緩沖效果。

那么,如何拉開(kāi)一定的間隔呢?也就是希望每次運(yùn)動(dòng)的快一點(diǎn),然后停留一會(huì)。其實(shí)也很簡(jiǎn)單,在之前的每個(gè)關(guān)鍵點(diǎn)前再添加一個(gè)相同的關(guān)鍵幀,比如在16.67%的前面一點(diǎn)6.67%,由于是相同的,所以這段時(shí)間內(nèi)是沒(méi)有動(dòng)畫(huà)的,也就相當(dāng)于停留了一會(huì)。

圖片圖片

用代碼實(shí)現(xiàn)就是:

@keyframes slide {
  0%,90%,100% {
    transform: translate(0%, 0%) scale(1);
  }
  6.67%,
  16.67% {
    transform: translate(120%, -30%) scale(0.9);
  }
  23.33%,
  33.33% {
    transform: translate(100%, -70%) scale(0.8);
  }
  40%,
  50% {
    transform: translate(0, -90%) scale(0.7);
  }
  56.67%,
  66.67% {
    transform: translate(-100%, -70%) scale(0.8);
  }
  73.33%,
  83.33% {
    transform: translate(-120%, -30%) scale(0.9);
  }
}

這樣是不是就好多了?

圖片圖片

實(shí)現(xiàn)了一個(gè),多個(gè)子元素也就好辦了。

<div class="item" style="--i: 0"></div>
<div class="item" style="--i: 1"></div>
<div class="item" style="--i: 2"></div>
<div class="item" style="--i: 3"></div>
<div class="item" style="--i: 4"></div>
<div class="item" style="--i: 5"></div>

我們給每個(gè)子元素加個(gè)CSS變量,然后給每個(gè)動(dòng)畫(huà)加個(gè)“負(fù)延遲”,讓這個(gè)動(dòng)畫(huà)提前運(yùn)行到指定位置;

.item{
   animation: slide 12s calc(-2s * var(--i)) infinite;
}

效果如下:

基本就實(shí)現(xiàn)這個(gè)這個(gè)輪播動(dòng)畫(huà),不過(guò)層級(jí)還有點(diǎn)問(wèn)題。

所以還需要再關(guān)鍵幀里加入層級(jí)變化;

@keyframes slide {
  0%,90%,100% {
    z-index: 4;
    transform: translate(0%, 0%) scale(1);
  }
  6.67%,
  16.67% {
    z-index: 3;
    transform: translate(120%, -30%) scale(0.9);
  }
  23.33%,
  33.33% {
    z-index: 2;
    transform: translate(100%, -70%) scale(0.8);
  }
  40%,
  50% {
    z-index: 1;
    transform: translate(0, -90%) scale(0.7);
  }
  56.67%,
  66.67% {
    z-index: 2;
    transform: translate(-100%, -70%) scale(0.8);
  }
  73.33%,
  83.33% {
    z-index: 3;
    transform: translate(-120%, -30%) scale(0.9);
  }
}

這樣就完美了。

這種實(shí)現(xiàn)兼容性最好,只用到了 CSS 動(dòng)畫(huà),兼容市面所有瀏覽器,可以放心使用

  • CSS 3d swiper (codepen.io)[1]
  • CSS 3d swiper (juejin.cn)[2]

三、CSS @property

其實(shí)目前來(lái)說(shuō),用上面這種方式就足夠了,沒(méi)有任何問(wèn)題。

不過(guò),上面對(duì)于中間停頓的處理方式可能有些繁瑣,下面再介紹另一種思路,可能更符合常規(guī)。

先思考一下,如果是用 JS要如何實(shí)現(xiàn)?是不是可以直接每隔2秒改變位移和縮放,然后通過(guò)transition實(shí)現(xiàn)過(guò)渡效果?

首先,我們還是需要像之前一樣,定義一些關(guān)鍵幀,不過(guò)不是直接改變位移和縮放,而是改變一些 CSS變量。

@keyframes slide {
  0%,100% {
    --translate: 0,0;
    --scale: 1;
    --z: 4;
  }
  16.67% {
    --translate: 120%,-30%;
    --scale: 0.9;
    --z: 3;
  }
  33.33% {
    --translate: 100%,-70%;
    --scale: 0.8;
    --z: 2;
  }
  50% {
    --translate: 0%,-90%;
    --scale: 0.7;
    --z: 1;
  }
  66.67% {
    --translate: -100%,-70%;
    --scale: 0.8;
    --z: 2;
  }
  83.33% {
    --translate: -120%,-30%;
    --scale: 0.9;
    --z: 3;
  }
}

然后每個(gè)子項(xiàng)就需要用transfrom來(lái)應(yīng)用這些變量了;

.item{
  transform: translate(var(--translate)) scale(var(--scale));
  transition: .5s transform;
  animation: slide 12s calc(-2s * var(--i)) infinite;
}

我們來(lái)看看效果:

好像并沒(méi)有過(guò)渡動(dòng)畫(huà)?這是因?yàn)閍nimation覆蓋了transition,所以需要分離開(kāi)來(lái),我們嵌套一層父級(jí)。

<div class="item-wrap" style="--i: 0">
  <div class="item"></div>
</div>
<div class="item-wrap" style="--i: 1">
  <div class="item"></div>
</div>
<div class="item-wrap" style="--i: 2">
  <div class="item"></div>
</div>
<div class="item-wrap" style="--i: 3">
  <div class="item"></div>
</div>
<div class="item-wrap" style="--i: 4">
  <div class="item"></div>
</div>
<div class="item-wrap" style="--i: 5">
  <div class="item"></div>
</div>

然后將動(dòng)畫(huà)寫(xiě)在父級(jí)上;

.item-wrap{
  animation: slide 12s calc(-2s * var(--i)) infinite;
  display: contents;
}

這樣就不影響了,效果如下:

不過(guò)還是有點(diǎn)怪怪的。這是因?yàn)閍nimation的默認(rèn)效果也是ease-in-out,所以有這種漸入漸出的效果。我們需要瞬間變化,不需要過(guò)渡效果,因?yàn)檫^(guò)渡效果可以由transition完成。

這里我們可以用steps來(lái)實(shí)現(xiàn),steps(1)表示直接切換,中間沒(méi)有任何過(guò)渡。

.item-wrap{
  animation: slide 12s calc(-2s * var(--i)) steps(1) infinite;
}

這樣效果就和前面基本一致了。

你也可以訪問(wèn)以下鏈接來(lái)查看實(shí)際效果:

  • CSS 3d swiper @property (codepen.io)[3]
  • CSS 3d swiper @property (juejin.cn)[4]

雖然里面沒(méi)有提到CSS @property,但實(shí)際上是依賴這個(gè)特性的,因此兼容性稍差,需要Safari 16.4+,F(xiàn)irefox目前還不支持。

四、CSS 樣式查詢

拋開(kāi)兼容性,其實(shí)還有一種方式可以實(shí)現(xiàn),而且更容易理解,也更符合JS的思路。

我們要做的動(dòng)畫(huà)很簡(jiǎn)單,只需要改變一個(gè) CSS變量就行,如下:

@property --index {
  syntax: "<number>";
  initial-value: 0;
  inherits: false;
}
@keyframes slide {
  0% {
    --index: 0;
  }
  100% {
    --index: 6;
  }
}

通過(guò)@property可以讓--index變量從0→6一次變化。

關(guān)于這個(gè)技巧,之前在多篇文章中都有提到。

你可能不需要 JS!CSS實(shí)現(xiàn)一個(gè)計(jì)時(shí)器。

如何讓CSS計(jì)數(shù)器支持小數(shù)的動(dòng)態(tài)變化?

還在使用定時(shí)器嗎?CSS 也能實(shí)現(xiàn)電子時(shí)鐘。

動(dòng)畫(huà)合成小技巧!CSS 實(shí)現(xiàn)動(dòng)感的倒計(jì)時(shí)效果。

自定義計(jì)數(shù)器小技巧!CSS 實(shí)現(xiàn)長(zhǎng)按點(diǎn)贊累積動(dòng)畫(huà)。

實(shí)現(xiàn)如下:

.item-wrap{
  display: contents;
  animation: slide 12s calc(-2s * var(--i)) steps(6) infinite;
}

這樣就實(shí)現(xiàn)了一個(gè)--index不斷變化的動(dòng)畫(huà)。

當(dāng)然僅僅只是這樣還不夠,我們需要根據(jù)這個(gè)變量來(lái)匹配具體的樣式,這就要用到CSS樣式查詢了,具體實(shí)現(xiàn)如下:

@container style(--index: 0) {
  .item {
    transform: translate(0, 0) scale(1);
    z-index: 4;
  }
}
@container style(--index: 1) {
  .item {
    transform: translate(120%, -30%) scale(0.9);
    z-index: 3;
  }
}
@container style(--index: 2) {
  .item {
    transform: translate(100%, -70%) scale(0.8);
    z-index: 2;
  }
}
@container style(--index: 3) {
  .item {
    transform: translate(0, -90%) scale(0.7);
    z-index: 1;
  }
}
@container style(--index: 4) {
  .item {
    transform: translate(-100%, -70%) scale(0.8);
    z-index: 2;
  }
}
@container style(--index: 5) {
  .item {
    transform: translate(-120%, -30%) scale(0.9);
    z-index: 3;
  }
}

這段應(yīng)該很好理解,比如@container style(--index: 5) 表示,當(dāng)查詢到--index為5的時(shí)候,下面的樣式就生效了,非常像通過(guò) JS 來(lái)改變類名一樣,這種方式也能實(shí)現(xiàn)類似的效果。

你也可以訪問(wèn)以下鏈接來(lái)查看實(shí)際效果:

  • CSS 3d swiper @style (codepen.io)[5]
  • CSS 3d swiper @style (juejin.cn)[6]

由于要用到樣式查詢,所以兼容性更差一點(diǎn),需要Chrome 111+,酌情使用。

五、總結(jié)一下

以上就是本文的全部?jī)?nèi)容了,共介紹了3種不同的實(shí)現(xiàn)思路,兼容性從高到低,大家可以自行選擇。

對(duì)了,還有一點(diǎn),有時(shí)候我們需要鼠標(biāo)hover時(shí)暫停動(dòng)畫(huà),這個(gè)就體現(xiàn)出CSS的優(yōu)勢(shì)了,直接用:hover實(shí)現(xiàn),類似這樣

.wrap:hover .item{
    animation-play-state: paused;
}

下面總結(jié)一下實(shí)現(xiàn)要點(diǎn):

  1. 整體看著是一個(gè)連貫的輪播效果,其實(shí)單獨(dú)看每一個(gè)子項(xiàng),都是完全相同的運(yùn)動(dòng)軌跡。
  2. 給每個(gè)子項(xiàng)不同的“負(fù)延遲”,就能形成一個(gè)完整的輪播效果。
  3. 動(dòng)畫(huà)本質(zhì)上是6個(gè)關(guān)鍵幀,只是位移和縮放的變化。
  4. 直接使用關(guān)鍵幀雖然有動(dòng)畫(huà),但是效果有點(diǎn)奇怪,每次改變位置的時(shí)候好像沒(méi)有停頓,顯得過(guò)渡有些緩慢。
  5. 可以手動(dòng)在每個(gè)關(guān)鍵點(diǎn)前再添加一個(gè)相同的關(guān)鍵幀,手動(dòng)停頓一下。
  6. 給每個(gè)子元素加個(gè)CSS變量,通過(guò)這個(gè)變量可以計(jì)算每個(gè)動(dòng)畫(huà)的“負(fù)延遲”,讓這個(gè)動(dòng)畫(huà)提前運(yùn)行到指定。
  7. 我們還定義一些關(guān)鍵幀,不過(guò)不是直接改變位移和縮放,而是改變一些 CSS變量。
  8. 這樣可以實(shí)現(xiàn)每隔2秒改變位移和縮放,然后通過(guò)transition實(shí)現(xiàn)過(guò)渡效果。
  9. 這種思路依賴CSS @property,兼容性稍差,需要Safari 16.4+,F(xiàn)irefox目前還不支持。
  10. 還可以通過(guò)樣式查詢,自動(dòng)匹配每種變量的位移和縮放,更符合常規(guī)思路,需要Chrome 111+
責(zé)任編輯:武曉燕 來(lái)源: 前端偵探
相關(guān)推薦

2022-07-08 09:27:48

CSSIFC模型

2022-09-19 19:16:42

輪播圖has

2022-05-06 09:00:56

CSS元素Flex

2022-10-09 09:30:33

CSS瀏覽器十六進(jìn)制

2023-11-08 10:12:40

架構(gòu)函數(shù)元素

2023-02-24 08:32:50

CSS漸變屬性

2022-06-16 07:50:35

數(shù)據(jù)結(jié)構(gòu)鏈表

2022-10-27 09:13:58

CSSGradient

2023-10-06 00:01:08

UML類圖圖形

2023-12-07 12:29:49

Nginx負(fù)載均衡策略

2024-03-12 08:37:32

asyncawaitJavaScript

2024-07-29 10:35:44

KubernetesCSI存儲(chǔ)

2023-08-22 10:25:19

CSS動(dòng)畫(huà)網(wǎng)頁(yè)

2024-02-19 07:52:40

CSSJS屬性

2024-05-30 09:43:00

2022-04-01 09:02:19

CSS選擇器HTML

2024-09-26 09:10:08

2024-02-02 11:03:11

React數(shù)據(jù)Ref

2023-08-08 08:23:08

Spring日志?線程池

2024-01-02 12:05:26

Java并發(fā)編程
點(diǎn)贊
收藏

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