使用mask-image實現(xiàn)星球大戰(zhàn)場景過渡效果
前言
大家有看過星球大戰(zhàn)這部電影嗎,里面有許多場景間的過渡效果看起來非常的絲滑,那我們能不能使用CSS來模擬實現(xiàn)一下呢?
漸變體驗
如果mask-image以圖像或漸變的形式出現(xiàn),則我們可以控制與元素的哪些像素是可見的,哪些像素是不可見的(透明)。當(dāng)mask-image應(yīng)用于元素時,它充當(dāng)一種映射,確定每個元素的可見性。
下面嘗試將兩張圖片使用mask-image實現(xiàn)交叉淡入淡出效果
<template>
  <div :class="$style.xq_outer">
    <div :class="$style.xq_bg"></div>
    <div :class="$style.xq_women"></div>
  </div>
</template>
<style lang="scss" module>
.xq_outer {
  position: relative;
  width: 600px;
  height: 360px;
  margin: 20px auto;
  background: red;
}
.xq_bg {
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url("/public/xq_bg.jpeg");
  background-size: 100% 100%;
}
.xq_women {
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url("/public/xq_women.jpeg");
  background-size: 100% 100%;
  -webkit-mask-image: linear-gradient(to right, transparent 30%, #fff 44%);
}
</style>效果是這樣的:

這里第一眼看上去你不會以為這就是一張圖片吧,其實這是由星球背景 + 人物兩張圖片“合成”的。

是不是有點PS的感覺了。
「原理是:第一個場景是星球,第二個場景是人物,直接位于第一個場景之上。在第二個場景中使用漸變蒙版使其左側(cè)透明,從而顯示出第一個場景?!?/p>
-webkit-mask-image為linear-gradient()從左到右漸變。
- 前三分之一是完全透明的,所以這部分人物圖片是不可見的,底下的星球圖片露出。
 - 中間的三分之一從透明變?yōu)椴煌该鞯陌咨瑘鼍爸饾u淡入。
 - 最后三分之一是完全不透明的白色,導(dǎo)致這部分人物圖片完全可見,底下的星球完全被蓋住。
 
水平擦除過渡
了解了上面這個效果的實現(xiàn)原理,我們就可以來著手實現(xiàn)第二個水平擦除效果了,從上面這個例子我們不難想象到只要蒙版拉伸到比實際場景更寬,然后動畫水平滑動,就能夠?qū)崿F(xiàn)這個水平擦除效果了。
.xq_outer {
  position: relative;
  width: 600px;
  height: 360px;
  margin: 20px auto;
}
.xq_bg {
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url("/public/xq_bg.jpeg");
  background-size: 100% 100%;
}
.xq_women {
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url("/public/xq_women.jpeg");
  background-size: 100% 100%;
  // -webkit-mask-image: linear-gradient(to right, transparent 30%, #fff 44%);
  -webkit-mask-image: linear-gradient(to right, transparent 48%, #fff 52%);
  -webkit-mask-size: 210%;
  -webkit-mask-position: left;
}
.xq_outer:is(:hover) .xq_women {
  -webkit-mask-position: right;
  transition: -webkit-mask-position 2s linear;
}效果如下:

「原理:蒙版的大小為-webkit-mask-size: 210%- 這為場景提供了 100% 的寬度,最初是完全透明的 + 10% 的淡入淡出 + 另一個 100% 的場景最終完全不透明?!?/p>
光圈擦除過渡
下面再來看一種光圈擦除效果,這里將會使用到@property自定義屬性,由于這個屬性還處于實驗階段,所以在將其用于生產(chǎn)之前,請仔細(xì)檢查瀏覽器兼容性表格。
大致的思路是:使用radial-gradient()在其中定義一個自定義屬性。然后我們可以對該自定義屬性進(jìn)行動畫處理以對漸變進(jìn)行動畫處理。但在此之前,我們需要將自定義屬性注冊到@property.
@property --r {
  syntax: "<percentage>";
  inherits: true;
  initial-value: -5%;
}
.xq_women {
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url("/public/xq_women.jpeg");
  background-size: 100% 100%;
  // -webkit-mask-image: linear-gradient(to right, transparent 30%, #fff 44%);
  // -webkit-mask-image: linear-gradient(to right, transparent 48%, #fff 52%);
  // -webkit-mask-size: 210%;
  // -webkit-mask-position: left;
  -webkit-mask-image: radial-gradient(
    circle,
    #fff calc(var(--r) - 5%),
    transparent calc(var(--r) + 5%)
  );
}
@keyframes circle {
  to {
    --r: 105%;
  }
}
.xq_outer:is(:hover) .xq_women {
  // -webkit-mask-position: right;
  // transition: -webkit-mask-position 2s linear;
  animation: circle 2s linear forwards;
}再來看看此時的效果:

「原理:隨著 --radius 的動畫化,radial-gradient() 中的色標(biāo)位置也是如此。它們被計算為 --radius 值的 -5% 和 +5%,以創(chuàng)建漸變淡入淡出,為擦拭提供柔和的邊緣?!?/p>
時鐘擦除過渡
再來看一個星球大戰(zhàn)中最具標(biāo)志性的擦除過渡——時鐘擦除過渡。這次我們使用conic-gradient()和動畫化一個自定義屬性angle值。
@property --angle {
  syntax: "<angle>";
  inherits: true;
  initial-value: -10deg;
}
.xq_women {
  position: absolute;
  width: 100%;
  height: 100%;
  background-image: url("/public/xq_women.jpeg");
  background-size: 100% 100%;
  -webkit-mask-image: conic-gradient(
      #fff 0deg,
      #fff calc(var(--angle) - 10deg),
      transparent calc(var(--angle) + 10deg),
      transparent 360deg
    ),
    conic-gradient(transparent 350deg, #fff 360deg);
  z-index: -1;
}
@keyframes ang {
  to {
    --angle: 370deg;
  }
}
.xq_outer:is(:hover) .xq_women {
  animation: ang 2s linear forwards;
  z-index: 1;
}效果如下:

「原理:第一個conic-gradient()動畫以創(chuàng)建時鐘擦除效果,但它在其起點(在 處0deg)留下了硬邊。這就是為什么要conic-gradient()在硬邊緣之前創(chuàng)建一個小的淡入淡出并將其軟化的原因。漸變結(jié)合在一起為場景創(chuàng)建蒙版?!?/p>
總結(jié)
現(xiàn)在的CSS功能越來越強(qiáng)大了,在本文中介紹了很多 CSS 成分,包括不同類型的漸變、注冊自定義屬性,當(dāng)然還有遮罩和動畫。這在以前,僅僅靠CSS是不可能實現(xiàn)的效果!















 
 
 






 
 
 
 